bonfida-utils 0.7.0

Various solana program writing utilities in use by Bonfida.
Documentation
use borsh::{BorshDeserialize, BorshSerialize};
use solana_program::pubkey::Pubkey;

pub trait BorshSize: BorshDeserialize + BorshSerialize {
    fn borsh_len(&self) -> usize;
}

impl BorshSize for () {
    fn borsh_len(&self) -> usize {
        0
    }
}

impl BorshSize for u8 {
    fn borsh_len(&self) -> usize {
        1
    }
}

impl BorshSize for u16 {
    fn borsh_len(&self) -> usize {
        2
    }
}

impl BorshSize for u32 {
    fn borsh_len(&self) -> usize {
        4
    }
}

impl BorshSize for u64 {
    fn borsh_len(&self) -> usize {
        8
    }
}

impl BorshSize for u128 {
    fn borsh_len(&self) -> usize {
        16
    }
}

impl BorshSize for i8 {
    fn borsh_len(&self) -> usize {
        1
    }
}

impl BorshSize for i16 {
    fn borsh_len(&self) -> usize {
        2
    }
}

impl BorshSize for i32 {
    fn borsh_len(&self) -> usize {
        4
    }
}

impl BorshSize for i64 {
    fn borsh_len(&self) -> usize {
        8
    }
}

impl BorshSize for i128 {
    fn borsh_len(&self) -> usize {
        16
    }
}

impl BorshSize for bool {
    fn borsh_len(&self) -> usize {
        1
    }
}

impl BorshSize for Pubkey {
    fn borsh_len(&self) -> usize {
        32
    }
}

impl BorshSize for String {
    fn borsh_len(&self) -> usize {
        4 + self.len()
    }
}

impl<T: BorshSize> BorshSize for Option<T> {
    fn borsh_len(&self) -> usize {
        match self.as_ref() {
            Some(a) => 1 + a.borsh_len(),
            None => 1,
        }
    }
}

impl<T: BorshSize> BorshSize for Vec<T> {
    fn borsh_len(&self) -> usize {
        if self.is_empty() {
            4
        } else {
            4 + self.len() * self[0].borsh_len()
        }
    }
}

#[cfg(test)]
mod tests {
    use super::BorshSize;
    use bonfida_macros::BorshSize;
    use borsh::{BorshDeserialize, BorshSerialize};
    use solana_program::pubkey::Pubkey;

    #[derive(BorshSerialize, BorshDeserialize, BorshSize)]
    struct TestStruct {
        a: u8,
        b: u16,
        c: u32,
        d: u64,
        e: u128,
        f: Pubkey,
        g: [u8; 32],
        h: [u64; 4],
        i: Option<String>,
        j: Option<u64>,
        k: Option<u64>,
    }

    #[derive(BorshSerialize, BorshDeserialize, BorshSize)]
    enum TestEnum {
        FirstVariant,
        SecondVariant,
    }

    #[test]
    fn functional() {
        let s = TestStruct {
            a: 0,
            b: 0,
            c: 0,
            d: 0,
            e: 0,
            f: Pubkey::new_unique(),
            g: [0; 32],
            h: [0; 4],
            i: Some("this is a test".to_string()),
            j: Some(0),
            k: None,
        };
        assert_eq!(
            s.borsh_len(),
            1 + 2 + 4 + 8 + 16 + 32 + 32 + 32 + 19 + 9 + 1
        );

        let v = TestEnum::FirstVariant;
        assert_eq!(v.borsh_len(), 1);
    }
}