substrate-stellar-sdk 0.3.0

A Substrate compatible SDK for Stellar
Documentation
use core::convert::AsRef;
use sp_std::vec::Vec;

use crate::StellarSdkError;

const ALPHABET: &'static [u8; 32] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";

fn ascii_to_value_5bit(char: u8) -> Option<u8> {
    match char as char {
        'a'..='z' => Some(char - ('a' as u8)),
        'A'..='Z' => Some(char - ('A' as u8)),
        '2'..='7' => Some(char - ('2' as u8) + 26),
        '0' => Some(14),
        '1' => Some(8),
        _ => None,
    }
}

pub fn encode<T: AsRef<[u8]>>(binary: T) -> Vec<u8> {
    let mut buffer = Vec::with_capacity(binary.as_ref().len() * 2);
    let mut shift = 3;
    let mut carry = 0;

    for byte in binary.as_ref().iter() {
        let value_5bit = if shift == 8 { carry } else { carry | ((*byte) >> shift) };
        buffer.push(ALPHABET[(value_5bit & 0x1f) as usize]);

        if shift > 5 {
            shift -= 5;
            let value_5bit = (*byte) >> shift;
            buffer.push(ALPHABET[(value_5bit & 0x1f) as usize]);
        }

        shift = 5 - shift;
        carry = *byte << shift;
        shift = 8 - shift;
    }

    if shift != 3 {
        buffer.push(ALPHABET[(carry & 0x1f) as usize]);
    }

    buffer
}

pub fn decode<T: AsRef<[u8]>>(string: T) -> Result<Vec<u8>, StellarSdkError> {
    let mut result = Vec::with_capacity(string.as_ref().len());
    let mut shift: i8 = 8;
    let mut carry: u8 = 0;

    for (position, ascii) in string.as_ref().iter().enumerate() {
        if *ascii as char == '=' {
            break
        }

        let value_5bit = ascii_to_value_5bit(*ascii);
        if let Some(value_5bit) = value_5bit {
            shift -= 5;
            if shift > 0 {
                carry |= value_5bit << shift;
            } else if shift < 0 {
                result.push(carry | (value_5bit >> -shift));
                shift += 8;
                carry = value_5bit << shift;
            } else {
                result.push(carry | value_5bit);
                shift = 8;
                carry = 0;
            }
        } else {
            return Err(StellarSdkError::InvalidBase32Character { at_position: position })
        }
    }

    if shift != 8 && carry != 0 {
        result.push(carry);
    }

    Ok(result)
}