atlas_arch/
deserialize.rs

1use std::{
2    io::{Error, ErrorKind, Read, Result},
3    ops::Deref,
4};
5
6use arch_program::account::AccountMeta;
7use borsh::BorshDeserialize;
8
9/// Trait for Borsh-deserializable types with a fixed discriminator prefix.
10///
11/// Implement for account or instruction data that begins with a static
12/// discriminator. `deserialize` should validate and strip the discriminator
13/// before deserializing the remaining bytes.
14pub trait AtlasDeserialize
15where
16    Self: Sized + BorshDeserialize,
17{
18    const DISCRIMINATOR: &'static [u8];
19
20    fn deserialize(data: &[u8]) -> Option<Self>;
21}
22
23pub fn extract_discriminator(length: usize, data: &[u8]) -> Option<(&[u8], &[u8])> {
24    log::trace!(
25        "extract_discriminator(length: {:?}, data: {:?})",
26        length,
27        data
28    );
29
30    if data.len() < length {
31        return None;
32    }
33
34    Some((&data[..length], &data[length..]))
35}
36
37/// Rearranges instruction `AccountMeta`s into a typed layout.
38///
39/// Use this to map positional accounts into a more descriptive structure,
40/// returning `None` when the layout is not satisfied.
41pub trait ArrangeAccounts {
42    type ArrangedAccounts;
43
44    fn arrange_accounts(accounts: &[AccountMeta]) -> Option<Self::ArrangedAccounts>;
45}
46
47#[derive(serde::Serialize, serde::Deserialize, Default, PartialEq, Eq, Clone)]
48pub struct PrefixString(pub String);
49
50impl Deref for PrefixString {
51    type Target = String;
52
53    fn deref(&self) -> &Self::Target {
54        &self.0
55    }
56}
57
58impl From<PrefixString> for String {
59    fn from(val: PrefixString) -> Self {
60        val.0
61    }
62}
63
64impl std::fmt::Debug for PrefixString {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        f.write_fmt(format_args!("{:?}", self.0))
67    }
68}
69
70impl BorshDeserialize for PrefixString {
71    #[inline]
72    fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
73        // read the length of the String
74        let mut buffer = vec![0u8; 4];
75        reader.read_exact(&mut buffer)?;
76        let length = u32::deserialize(&mut buffer.as_slice())?;
77        let mut buffer = vec![0u8; length as usize];
78        reader.read_exact(&mut buffer)?;
79
80        Ok(Self(String::from_utf8(buffer).map_err(|_| {
81            Error::new(ErrorKind::InvalidData, "invalid utf8")
82        })?))
83    }
84}
85
86#[derive(serde::Serialize, Default, serde::Deserialize, PartialEq, Eq, Clone)]
87pub struct U64PrefixString(pub String);
88
89impl Deref for U64PrefixString {
90    type Target = String;
91
92    fn deref(&self) -> &Self::Target {
93        &self.0
94    }
95}
96
97impl From<U64PrefixString> for String {
98    fn from(val: U64PrefixString) -> Self {
99        val.0
100    }
101}
102
103impl std::fmt::Debug for U64PrefixString {
104    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
105        f.write_fmt(format_args!("{:?}", self.0))
106    }
107}
108
109impl BorshDeserialize for U64PrefixString {
110    #[inline]
111    fn deserialize_reader<R: Read>(reader: &mut R) -> Result<Self> {
112        // read the length of the String
113        let mut buffer = vec![0u8; 8];
114        reader.read_exact(&mut buffer)?;
115        let length = u64::deserialize(&mut buffer.as_slice())?;
116        let mut buffer = vec![0u8; length as usize];
117        reader.read_exact(&mut buffer)?;
118
119        Ok(Self(String::from_utf8(buffer).map_err(|_| {
120            Error::new(ErrorKind::InvalidData, "invalid utf8")
121        })?))
122    }
123}