ps-hkey 0.1.0-34

This crate defines the hashkey format and provides methods for resolving them
Documentation
use std::{future::Future, pin::Pin, sync::Arc};

use ps_datachunk::{Bytes, DataChunk};
use ps_promise::PromiseRejection;

use crate::{
    long::{
        long_hkey_expanded::{
            constants::{LHKEY_LEVEL_MAX_LENGTH, LHKEY_SEGMENT_MAX_LENGTH},
            methods::update::helpers::{calculate_depth, calculate_segment_length},
        },
        LongHkeyExpanded,
    },
    AsyncStore, Hkey, HkeyError, Range,
};

impl LongHkeyExpanded {
    pub fn from_blob_async_box<'a, C, E, S>(
        store: &'a S,
        data: &'a [u8],
    ) -> Pin<Box<dyn Future<Output = Result<Self, E>> + Send + Sync + 'a>>
    where
        C: DataChunk + Send + Unpin,
        E: From<HkeyError> + PromiseRejection + Send,
        S: AsyncStore<Chunk = C, Error = E> + Sync,
    {
        Box::pin(async move { Self::from_blob_async(store, data).await })
    }

    pub async fn from_blob_async<C, E, S>(store: &S, data: &[u8]) -> Result<Self, E>
    where
        C: DataChunk + Send + Unpin,
        E: From<HkeyError> + PromiseRejection + Send,
        S: AsyncStore<Chunk = C, Error = E> + Sync,
    {
        let depth = calculate_depth(0, data.len());

        let parts: Result<Vec<(Range, Hkey)>, E> = if data.len() > LHKEY_LEVEL_MAX_LENGTH {
            let segment_length = calculate_segment_length(depth);

            let mut chunks = Vec::new();

            for (index, chunk) in data.chunks(segment_length).enumerate() {
                let start = index * segment_length;
                let end = start + chunk.len();
                let hkey = Self::from_blob_async_box(store, chunk)
                    .await?
                    .shrink_async(store)
                    .await?;

                chunks.push((start..end, hkey));
            }

            Ok(chunks)
        } else {
            let mut chunks = Vec::new();

            for (index, chunk) in data.chunks(LHKEY_SEGMENT_MAX_LENGTH).enumerate() {
                let start = index * LHKEY_SEGMENT_MAX_LENGTH;
                let end = start + chunk.len();
                let hkey = store.put(Bytes::copy_from_slice(chunk)).await?;

                chunks.push((start..end, hkey));
            }

            Ok(chunks)
        };

        let parts = Arc::from(parts?.into_boxed_slice());
        let lhkey = Self::new(depth, data.len(), parts);

        Ok(lhkey)
    }
}