1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use super::{AsyncStdReader, ReadSeek};
use async_std::io::Read;
use hff_core::{
    read::{Hff, Inspection},
    ChunkCache, Result, NE, OP,
};

/// Opens the input and maintains it for random access to the
/// metadata and chunks.
pub async fn open(mut source: impl ReadSeek + 'static) -> Result<Hff<AsyncStdReader>> {
    let header = AsyncStdReader::read_header(&mut source).await?;
    let (tables, chunks) = if header.is_native_endian() {
        (
            AsyncStdReader::read_tables::<NE>(&mut source, header.table_count()).await?,
            AsyncStdReader::read_chunks::<NE>(&mut source, header.chunk_count()).await?,
        )
    } else {
        (
            AsyncStdReader::read_tables::<OP>(&mut source, header.table_count()).await?,
            AsyncStdReader::read_chunks::<OP>(&mut source, header.chunk_count()).await?,
        )
    };
    Ok(Hff::new(
        AsyncStdReader::new(source),
        header,
        tables,
        chunks,
    ))
}

/// Reads an entire Hff into memory.
pub async fn read(mut source: &mut (dyn Read + std::marker::Unpin)) -> Result<Hff<ChunkCache>> {
    let header = AsyncStdReader::read_header(&mut source).await?;
    let (tables, chunks) = if header.is_native_endian() {
        (
            AsyncStdReader::read_tables::<NE>(&mut source, header.table_count()).await?,
            AsyncStdReader::read_chunks::<NE>(&mut source, header.chunk_count()).await?,
        )
    } else {
        (
            AsyncStdReader::read_tables::<OP>(&mut source, header.table_count()).await?,
            AsyncStdReader::read_chunks::<OP>(&mut source, header.chunk_count()).await?,
        )
    };
    let cache = AsyncStdReader::read_body(&mut source, tables.len(), chunks.len()).await?;
    Ok(Hff::new(cache, header, tables, chunks))
}

/// Read the structure of a Hff into memory.  Provides access
/// only to the structure without any of the metadata or chunk
/// data available.
pub async fn inspect(mut source: &mut (dyn Read + std::marker::Unpin)) -> Result<Hff<Inspection>> {
    let header = AsyncStdReader::read_header(&mut source).await?;
    let (tables, chunks) = if header.is_native_endian() {
        (
            AsyncStdReader::read_tables::<NE>(&mut source, header.table_count()).await?,
            AsyncStdReader::read_chunks::<NE>(&mut source, header.chunk_count()).await?,
        )
    } else {
        (
            AsyncStdReader::read_tables::<OP>(&mut source, header.table_count()).await?,
            AsyncStdReader::read_chunks::<OP>(&mut source, header.chunk_count()).await?,
        )
    };
    Ok(Hff::new(Inspection, header, tables, chunks))
}