solana-tool 0.1.1

solana tool, such as data parsers.
Documentation
/// reader associated with byte arrays module
pub mod reader {
    use solana_sdk::pubkey::Pubkey;
    pub fn r_u8(data: &[u8], offset: usize) -> u8 {
        if data.len() <= offset {
            return 0;
        }
        data[offset]
    }
    pub fn r_u16(data: &[u8], offset: usize) -> u16 {
        if data.len() < offset + 2 {
            return 0;
        }
        u16::from_le_bytes(data[offset..offset + 2].try_into().unwrap())
    }
    pub fn r_u32(data: &[u8], offset: usize) -> u32 {
        if data.len() < offset + 4 {
            return 0;
        }
        u32::from_le_bytes(data[offset..offset + 4].try_into().unwrap())
    }
    pub fn r_u64(data: &[u8], offset: usize) -> u64 {
        if data.len() < offset + 8 {
            return 0;
        }
        u64::from_le_bytes(data[offset..offset + 8].try_into().unwrap())
    }
    pub fn r_u128(data: &[u8], offset: usize) -> u128 {
        if data.len() < offset + 16 {
            return 0;
        }
        u128::from_le_bytes(data[offset..offset + 16].try_into().unwrap())
    }
    pub fn r_pubkey(data: &[u8], offset: usize) -> Pubkey {
        if data.len() < offset + 32 {
            return Pubkey::default();
        }
        Pubkey::new_from_array(data[offset..offset + 32].try_into().unwrap())
    }
    pub fn r_string(data: &[u8], offset: usize) -> String {
        if data.len() <= offset {
            return String::new();
        }

        let len = data[offset] as usize;
        if data.len() < offset + 1 + len {
            return String::new();
        }

        String::from_utf8_lossy(&data[offset + 1..offset + 1 + len]).to_string()
    }
    pub fn r_bool(data: &[u8], offset: usize) -> bool {
        r_u8(data, offset) != 0
    }
}

/// account data analysis tools module
pub mod account {
    use std::sync::Arc;

    use solana_client::nonblocking::rpc_client::RpcClient;
    use solana_sdk::pubkey::Pubkey;
    /// parse spl account info
    pub fn parse_spl_account_info(data: &[u8]) -> Result<(Pubkey, Pubkey, f64), String> {
        if data.len() < 72 {
            return Err("account data length error".to_string());
        }
        // mint
        let mint_address = Pubkey::new_from_array(data[..32].try_into().unwrap());
        // owner
        let owner_address = Pubkey::new_from_array(data[32..64].try_into().unwrap());
        // amount
        let amount = u64::from_le_bytes(data[64..72].try_into().unwrap());
        Ok((mint_address, owner_address, amount as f64))
    }
    /// get spl token balance
    /// # address
    /// spl token address
    pub async fn get_spl_token_balance(
        client: Arc<RpcClient>,
        address: Pubkey,
    ) -> Result<f64, String> {
        match client.get_account_data(&address).await {
            Ok(data) => {
                if data.len() < 72 {
                    return Err("Account data too short".to_string());
                }
                match parse_spl_account_info(&data) {
                    Ok(account) => return Ok(account.2),
                    Err(e) => return Err(e),
                }
            }
            Err(e) => return Err(format!("{:?}", e)),
        }
    }
}

/// unit processing module
pub mod unit {
    /// conver balance
    pub fn conver_balance(balance: f64, decimal: u8) -> f64 {
        balance as f64 / 10f64.powi(decimal as i32)
    }
}