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
67
68
69
use bytes::Bytes;
use serde::Serialize;
use ts_rs::TS;

use std::convert::TryFrom;

use crate::{envelope, index_v4};

pub mod errors;

#[derive(Serialize, TS)]
#[ts(export)]
pub struct IndexStatistics {
    version: String,
    document_count: usize,
}

/// An index-version-agnostic wrapper type to represent a usable search index.
pub struct ParsedIndex {
    pub(crate) value: IndexType,
}

impl ParsedIndex {
    pub fn stats(&self) -> IndexStatistics {
        match &self.value {
            IndexType::V4Index(v4_index) => IndexStatistics {
                version: "4".to_string(),
                document_count: v4_index.documents.len(),
            },
        }
    }
}

pub(crate) enum IndexType {
    V4Index(index_v4::Index),
}

pub(super) fn parse(bytes: Bytes) -> Result<ParsedIndex, errors::IndexParseError> {
    let envelope = envelope::Envelope::try_from(bytes)?;

    match envelope.prefix {
        envelope::Prefix::StorkV4Root => {
            let root = index_v4::RootChunk::try_from(envelope.bytes)?;
            let index = index_v4::Index::from(root);
            Ok(ParsedIndex {
                value: IndexType::V4Index(index),
            })
        }

        envelope::Prefix::StorkV4Part => Err(errors::IndexParseError::TriedParsingChunkAsRoot),
    }
}

pub(super) fn add_sidecar_bytes_to_index(
    index: &mut ParsedIndex,
    bytes: Bytes,
) -> Result<(), errors::IndexParseError> {
    let envelope = envelope::Envelope::try_from(bytes)?;
    let chunk = index_v4::Chunk::try_from(envelope.bytes)?;

    match (envelope.prefix, &mut index.value) {
        (envelope::Prefix::StorkV4Part, IndexType::V4Index(v4_index)) => {
            v4_index.add_chunk(&chunk);
            Ok(())
        }

        (envelope::Prefix::StorkV4Root, _) => Err(errors::IndexParseError::TriedParsingChunkAsRoot),
    }
}