accumulators 0.5.1

Complete package of multiple Accumulators with Stores and hashing functions (Hashers)
use crate::hasher::{byte_size, HasherError, HashingFunction};

use super::super::Hasher;
use starknet_crypto::{poseidon_hash, poseidon_hash_many, poseidon_hash_single, Felt};

/// Hasher for Stark Poseidon
#[derive(Debug, Clone)]
pub struct StarkPoseidonHasher {
    /// The block size in bits for Stark Poseidon is 252
    block_size_bits: usize,
    /// Boolean flag to indicate whether to pad the hash with zeros
    should_pad: bool,
}

impl Hasher for StarkPoseidonHasher {
    fn get_name(&self) -> HashingFunction {
        HashingFunction::Poseidon
    }

    /// Hashes a data which is a vector of strings
    ///
    /// NOTE: data should be more than 1 element
    fn hash(&self, data: Vec<String>) -> Result<String, HasherError> {
        for element in &data {
            self.is_element_size_valid(element)?;
        }

        let field_elements: Vec<Felt> =
            data.iter().map(|e| e.parse().unwrap_or_default()).collect();

        let hash_core = match field_elements.len() {
            0 => return Err(HasherError::InvalidElementsLength),
            1 => poseidon_hash_single(field_elements[0]),
            2 => poseidon_hash(field_elements[0], field_elements[1]),
            _ => poseidon_hash_many(&field_elements),
        };

        let mut hash = format!("{hash_core:x}");
        if self.should_pad {
            hash = format!("{hash:0>63}");
        }
        let hash = format!("0x{hash}");
        Ok(hash)
    }

    fn is_element_size_valid(&self, element: &str) -> Result<bool, HasherError> {
        let size = byte_size(element);
        if size <= self.block_size_bits {
            Ok(true)
        } else {
            Err(HasherError::InvalidElementSize {
                element_size: size,
                block_size_bits: self.block_size_bits,
            })
        }
    }

    fn hash_single(&self, data: &str) -> Result<String, HasherError> {
        self.hash(vec![data.to_string()])
    }

    fn get_genesis(&self) -> Result<String, HasherError> {
        let genesis_str = "brave new world";
        let hex_str = format!("0x{}", hex::encode(genesis_str));
        self.hash_single(&hex_str)
    }

    fn get_block_size_bits(&self) -> usize {
        self.block_size_bits
    }
}

impl StarkPoseidonHasher {
    pub fn new(should_pad: Option<bool>) -> Self {
        Self {
            block_size_bits: 252,
            should_pad: should_pad.unwrap_or(false),
        }
    }
}

impl Default for StarkPoseidonHasher {
    fn default() -> Self {
        Self::new(None)
    }
}