tycho 0.1.2

A minimal, self-describing and traversable binary data format designed around rust and the serde data model.
Documentation
use std::collections::HashMap;
use std::io::Cursor;

use futures::future::{BoxFuture, FutureExt};
use tokio::io::AsyncRead;

use crate::Element;
use crate::error::TychoResult;
use crate::read::async_::func::{read_byte_async, read_bytes_async};
use crate::read::async_::length::read_length_async;
use crate::read::async_::string::read_tstring_async;
use crate::read::async_::value::{read_value_async, read_value_ident_async};
use crate::read::element::parse_element_ident;
use crate::types::ident::{ElementIdent, ValueIdent};

pub(crate) async fn read_element_ident_async<R: AsyncRead + Unpin>(reader: &mut R) -> TychoResult<ElementIdent> {
   parse_element_ident(read_byte_async(reader).await?)
}

pub(crate) fn read_element_async<'a, R: AsyncRead + Unpin + Send>(reader: &'a mut R) -> BoxFuture<'a, TychoResult<Element>> {
    async move {
        let ident = read_element_ident_async(reader).await?;

        match ident {
            ElementIdent::Unit => Ok(Element::Unit),
            ElementIdent::Value => {
                let ident = read_value_ident_async(reader).await?;
                Ok(Element::Value(read_value_async(reader, &ident).await?))
            },
            ElementIdent::Some => Ok(Element::Option(Some(Box::new(read_element_async(reader).await?)))),
            ElementIdent::None => Ok(Element::Option(None)),
            ElementIdent::Variant => Ok(Element::Variant(
                read_tstring_async(reader).await?,
                Box::new(read_element_async(reader).await?)
            )),
            ElementIdent::Struct => {
                let size = read_length_async(reader).await?;
                let mut items = HashMap::new();
                let mut buffer = Cursor::new(read_bytes_async(reader, size).await?);

                loop {
                    if buffer.position() == size as u64 { break; }

                    let key = read_tstring_async(&mut buffer).await?;
                    let value = read_element_async(&mut buffer).await?;

                    items.insert(key, value);
                }

                Ok(Element::Struct(items))
            }
            ElementIdent::List => {
                let size = read_length_async(reader).await?;
                let mut items = Vec::new();
                let mut buffer = Cursor::new(read_bytes_async(reader, size).await?);

                loop {
                    if buffer.position() == size as u64 { break; }
                    items.push(read_element_async(&mut buffer).await?);
                }

                Ok(Element::List(items))
            },
            ElementIdent::Array => {
                let array_type = read_value_ident_async(reader).await?;

                if let ValueIdent::Null = &array_type {
                    Ok(Element::Array(ValueIdent::Null, Vec::new()))
                } else {
                    let size = read_length_async(reader).await?;
                    let mut items = Vec::new();
                    let mut buffer = Cursor::new(read_bytes_async(reader, size).await?);

                    loop {
                        if buffer.position() == size as u64 { break; }
                        items.push(read_value_async(&mut buffer, &array_type).await?);
                    }

                    Ok(Element::Array(array_type, items))
                }
            },
            ElementIdent::Map => {
                let key_type = read_value_ident_async(reader).await?;

                if let ValueIdent::Null = &key_type {
                    Ok(Element::Map(ValueIdent::Null, HashMap::new()))
                } else {
                    let size = read_length_async(reader).await?;
                    let mut items = HashMap::new();
                    let mut buffer = Cursor::new(read_bytes_async(reader, size).await?);

                    loop {
                        if buffer.position() == size as u64 { break; }

                        let key = read_value_async(&mut buffer, &key_type).await?;
                        let value = read_element_async(&mut buffer).await?;

                        items.insert(key, value);
                    }

                    Ok(Element::Map(key_type, items))
                }
            },
            ElementIdent::Compression => {
                let size = read_length_async(reader).await?;
                let mut buffer = Cursor::new(read_bytes_async(reader, size).await?);
                Ok(Element::Compression(Box::new(read_element_async(&mut buffer).await?)))
            }
        }
    }.boxed()
}