Skip to content

Commit 755df53

Browse files
committed
use concrete type over trait
1 parent bd4974e commit 755df53

File tree

3 files changed

+89
-95
lines changed

3 files changed

+89
-95
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use pinocchio::{account_info::AccountInfo, instruction::AccountMeta, pubkey::Pubkey};
22

3-
use crate::InvokeParts;
3+
use crate::{InstructionData, InvokeParts};
44

55
/// Allocate space for and assign an account at an address derived
66
/// from a base public key and a seed.
@@ -33,39 +33,36 @@ const N_ACCOUNTS: usize = 2;
3333
const N_ACCOUNT_METAS: usize = 2;
3434
const DATA_LEN: usize = 112;
3535

36-
impl<'a, 'b, 'c> InvokeParts for AllocateWithSeed<'a, 'b, 'c> {
37-
type Accounts = [&'a AccountInfo; N_ACCOUNTS];
38-
type AccountMetas = [AccountMeta<'a>; N_ACCOUNT_METAS];
39-
type InstructionData = [u8; DATA_LEN];
36+
impl<'a, 'b, 'c> From<AllocateWithSeed<'a, 'b, 'c>>
37+
for InvokeParts<'a, N_ACCOUNTS, N_ACCOUNT_METAS, DATA_LEN>
38+
{
39+
fn from(value: AllocateWithSeed<'a, 'b, 'c>) -> Self {
40+
Self {
41+
accounts: [value.account, value.base],
42+
account_metas: [
43+
AccountMeta::writable_signer(value.account.key()),
44+
AccountMeta::readonly_signer(value.base.key()),
45+
],
46+
instruction_data: {
47+
// instruction data
48+
// - [0..4 ]: instruction discriminator
49+
// - [4..36 ]: base pubkey
50+
// - [36..44]: seed length
51+
// - [44.. ]: seed (max 32)
52+
// - [.. +8]: account space
53+
// - [.. +32]: owner pubkey
54+
let mut instruction_data = [0; DATA_LEN];
55+
instruction_data[0] = 9;
56+
instruction_data[4..36].copy_from_slice(value.base.key());
57+
instruction_data[36..44]
58+
.copy_from_slice(&u64::to_le_bytes(value.seed.len() as u64));
4059

41-
fn accounts(&self) -> Self::Accounts {
42-
[self.account, self.base]
43-
}
44-
45-
fn account_metas(&self) -> Self::AccountMetas {
46-
[
47-
AccountMeta::writable_signer(self.account.key()),
48-
AccountMeta::readonly_signer(self.base.key()),
49-
]
50-
}
51-
52-
fn instruction_data(&self) -> (Self::InstructionData, usize) {
53-
// instruction data
54-
// - [0..4 ]: instruction discriminator
55-
// - [4..36 ]: base pubkey
56-
// - [36..44]: seed length
57-
// - [44.. ]: seed (max 32)
58-
// - [.. +8]: account space
59-
// - [.. +32]: owner pubkey
60-
let mut instruction_data = [0; DATA_LEN];
61-
instruction_data[0] = 9;
62-
instruction_data[4..36].copy_from_slice(self.base.key());
63-
instruction_data[36..44].copy_from_slice(&u64::to_le_bytes(self.seed.len() as u64));
64-
65-
let offset = 44 + self.seed.len();
66-
instruction_data[44..offset].copy_from_slice(self.seed.as_bytes());
67-
instruction_data[offset..offset + 8].copy_from_slice(&self.space.to_le_bytes());
68-
instruction_data[offset + 8..offset + 40].copy_from_slice(self.owner.as_ref());
69-
(instruction_data, offset + 40)
60+
let offset = 44 + value.seed.len();
61+
instruction_data[44..offset].copy_from_slice(value.seed.as_bytes());
62+
instruction_data[offset..offset + 8].copy_from_slice(&value.space.to_le_bytes());
63+
instruction_data[offset + 8..offset + 40].copy_from_slice(value.owner.as_ref());
64+
InstructionData::Truncated((instruction_data, offset + 40))
65+
},
66+
}
7067
}
7168
}
+19-25
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use pinocchio::{account_info::AccountInfo, instruction::AccountMeta};
22

3-
use crate::InvokeParts;
3+
use crate::{InstructionData, InvokeParts};
44

55
/// Transfer lamports.
66
///
@@ -22,29 +22,23 @@ const N_ACCOUNTS: usize = 2;
2222
const N_ACCOUNT_METAS: usize = 2;
2323
const DATA_LEN: usize = 12;
2424

25-
impl<'a> InvokeParts for Transfer<'a> {
26-
type Accounts = [&'a AccountInfo; N_ACCOUNTS];
27-
type AccountMetas = [AccountMeta<'a>; N_ACCOUNT_METAS];
28-
type InstructionData = [u8; DATA_LEN];
29-
30-
fn accounts(&self) -> Self::Accounts {
31-
[self.to, self.from]
32-
}
33-
34-
fn account_metas(&self) -> Self::AccountMetas {
35-
[
36-
AccountMeta::writable_signer(self.from.key()),
37-
AccountMeta::writable(self.to.key()),
38-
]
39-
}
40-
41-
fn instruction_data(&self) -> (Self::InstructionData, usize) {
42-
// instruction data
43-
// - [0..4 ]: instruction discriminator
44-
// - [4..12]: lamports amount
45-
let mut instruction_data = [0; DATA_LEN];
46-
instruction_data[0] = 2;
47-
instruction_data[4..12].copy_from_slice(&self.lamports.to_le_bytes());
48-
(instruction_data, DATA_LEN)
25+
impl<'a> From<Transfer<'a>> for InvokeParts<'a, N_ACCOUNTS, N_ACCOUNT_METAS, DATA_LEN> {
26+
fn from(value: Transfer<'a>) -> Self {
27+
InvokeParts {
28+
accounts: [value.to, value.from],
29+
account_metas: [
30+
AccountMeta::writable_signer(value.from.key()),
31+
AccountMeta::writable(value.to.key()),
32+
],
33+
instruction_data: {
34+
// instruction data
35+
// - [0..4 ]: instruction discriminator
36+
// - [4..12]: lamports amount
37+
let mut instruction_data = [0; DATA_LEN];
38+
instruction_data[0] = 2;
39+
instruction_data[4..12].copy_from_slice(&value.lamports.to_le_bytes());
40+
InstructionData::Full(instruction_data)
41+
},
42+
}
4943
}
5044
}

programs/system/src/lib.rs

+39-36
Original file line numberDiff line numberDiff line change
@@ -11,61 +11,64 @@ pub mod instructions;
1111

1212
pinocchio_pubkey::declare_id!("11111111111111111111111111111111");
1313

14-
pub trait InvokeParts {
15-
type Accounts;
16-
type AccountMetas;
17-
type InstructionData;
14+
pub struct InvokeParts<'a, const N: usize, const M: usize, const J: usize> {
15+
pub accounts: [&'a AccountInfo; N],
16+
pub account_metas: [AccountMeta<'a>; M],
17+
pub instruction_data: InstructionData<J>,
18+
}
1819

19-
fn accounts(&self) -> Self::Accounts;
20-
fn account_metas(&self) -> Self::AccountMetas;
21-
fn instruction_data(&self) -> (Self::InstructionData, usize);
20+
pub enum InstructionData<const N: usize> {
21+
Full([u8; N]),
22+
Truncated(([u8; N], usize)),
2223
}
2324

24-
pub trait Invoke<const N: usize>: Sized {
25+
impl<const N: usize> InstructionData<N> {
26+
pub fn data(&self) -> &[u8] {
27+
match *self {
28+
InstructionData::Full(ref data) => data,
29+
InstructionData::Truncated((ref data, end)) => &data[..end],
30+
}
31+
}
32+
}
33+
34+
pub trait Invoke<'a, const N: usize, const M: usize, const J: usize>:
35+
Into<InvokeParts<'a, N, M, J>>
36+
{
2537
fn invoke(self) -> pinocchio::ProgramResult {
2638
self.invoke_signed(&[])
2739
}
2840

2941
fn invoke_signed(self, signers: &[Signer]) -> pinocchio::ProgramResult {
30-
self.invoke_invoker(signers, |ix, acc, sigs| cpi::invoke_signed(&ix, acc, sigs))
42+
invoke_invoker(self.into(), signers, |ix, acc, sigs| {
43+
cpi::invoke_signed(&ix, acc, sigs)
44+
})
3145
}
3246

3347
unsafe fn invoke_access_unchecked(self) -> pinocchio::ProgramResult {
3448
self.invoke_singed_access_unchecked(&[])
3549
}
3650

3751
unsafe fn invoke_singed_access_unchecked(self, signers: &[Signer]) -> pinocchio::ProgramResult {
38-
self.invoke_invoker(signers, |ix, acc, sigs| unsafe {
52+
invoke_invoker(self.into(), signers, |ix, acc, sigs| unsafe {
3953
cpi::invoke_signed_access_unchecked(&ix, acc, sigs)
4054
})
4155
}
42-
43-
fn invoke_invoker(
44-
self,
45-
signers: &[Signer],
46-
invoker: impl FnOnce(Instruction, &[&AccountInfo; N], &[Signer]) -> pinocchio::ProgramResult,
47-
) -> pinocchio::ProgramResult;
4856
}
4957

50-
impl<'a, const N: usize, const M: usize, const J: usize, T> Invoke<N> for T
51-
where
52-
T: InvokeParts<
53-
Accounts = [&'a AccountInfo; N],
54-
AccountMetas = [AccountMeta<'a>; M],
55-
InstructionData = [u8; J],
56-
>,
58+
impl<'a, const N: usize, const M: usize, const J: usize, T> Invoke<'a, N, M, J> for T where
59+
T: Into<InvokeParts<'a, N, M, J>>
5760
{
58-
fn invoke_invoker(
59-
self,
60-
signers: &[Signer],
61-
invoker: impl FnOnce(Instruction, &[&AccountInfo; N], &[Signer]) -> pinocchio::ProgramResult,
62-
) -> pinocchio::ProgramResult {
63-
let (data, end) = self.instruction_data();
64-
let instruction = Instruction {
65-
program_id: &crate::ID,
66-
accounts: &self.account_metas(),
67-
data: &data[..end],
68-
};
69-
invoker(instruction, &self.accounts(), signers)
70-
}
61+
}
62+
63+
fn invoke_invoker<'a, const N: usize, const M: usize, const J: usize>(
64+
invoke_parts: InvokeParts<'a, N, M, J>,
65+
signers: &[Signer],
66+
invoker: impl FnOnce(Instruction, &[&AccountInfo; N], &[Signer]) -> pinocchio::ProgramResult,
67+
) -> pinocchio::ProgramResult {
68+
let instruction = Instruction {
69+
program_id: &crate::ID,
70+
accounts: &invoke_parts.account_metas,
71+
data: invoke_parts.instruction_data.data(),
72+
};
73+
invoker(instruction, &invoke_parts.accounts, signers)
7174
}

0 commit comments

Comments
 (0)