sview_fmindex/
load_from_blob.rs1use crate::{
2 FmIndex,
3 Position, Block,
5 components::{
6 Header, View,
7 MagicNumber, TextEncoder, CountArrayHeader, SuffixArrayHeader, BwmHeader,
9 CountArrayView, SuffixArrayView, BwmView,
11 },
12};
13
14#[derive(Debug, thiserror::Error)]
16pub enum LoadError {
17 #[error("Invalid FM-index format. The data does not appear to be a valid FM-index blob.")]
19 InvalidFormat,
20
21 #[error("Mismatched blob size: headers indicate a total size of {0} bytes, but the provided blob is {1} bytes.")]
23 MismatchedBlobSize(usize, usize),
24}
25
26
27impl<'a, P: Position, B: Block, E: TextEncoder> FmIndex<'a, P, B, E> {
28 pub fn load(blob: &'a [u8]) -> Result<Self, LoadError> {
30 let (magic_number, remaining_bytes) = MagicNumber::read_from_blob::<B>(blob);
32 if !(magic_number.is_valid() && magic_number.is_supported_version()) {
33 return Err(LoadError::InvalidFormat);
34 }
35 let (text_encoder, remaining_bytes) = E::read_from_blob::<B>(remaining_bytes);
36 let (count_array_header, remaining_bytes) = CountArrayHeader::read_from_blob::<B>(remaining_bytes);
37 let (suffix_array_header, remaining_bytes) = SuffixArrayHeader::read_from_blob::<B>(remaining_bytes);
38 let (bwm_header, body_blob) = BwmHeader::read_from_blob::<B>(remaining_bytes);
39
40 let actual_body_size = body_blob.len();
42 let expected_body_size = {
43 CountArrayView::<P>::aligned_body_size::<B>(&count_array_header)
44 + SuffixArrayView::<P>::aligned_body_size::<B>(&suffix_array_header)
45 + BwmView::<P, B>::aligned_body_size::<B>(&bwm_header)
46 };
47 if actual_body_size != expected_body_size {
48 let header_size = {
49 magic_number.aligned_size::<B>()
50 + text_encoder.aligned_size::<B>()
51 + count_array_header.aligned_size::<B>()
52 + suffix_array_header.aligned_size::<B>()
53 + bwm_header.aligned_size::<B>()
54 };
55 return Err(LoadError::MismatchedBlobSize(
56 header_size + expected_body_size,
57 header_size + actual_body_size,
58 ));
59 }
60
61 let mut body_start_index = 0;
64 let mut body_end_index = CountArrayView::<P>::aligned_body_size::<B>(&count_array_header);
65 let count_array_view = CountArrayView::<P>::load_from_body::<B>(&count_array_header, &body_blob[body_start_index..body_end_index]);
66 body_start_index = body_end_index;
68 body_end_index += SuffixArrayView::<P>::aligned_body_size::<B>(&suffix_array_header);
69 let suffix_array_view = SuffixArrayView::<P>::load_from_body::<B>(&suffix_array_header, &body_blob[body_start_index..body_end_index]);
70 body_start_index = body_end_index;
72 body_end_index += BwmView::<P, B>::aligned_body_size::<B>(&bwm_header);
73 let bwm_view = BwmView::<P, B>::load_from_body::<B>(&bwm_header, &body_blob[body_start_index..body_end_index]);
74
75 Ok(Self {
76 source_blob: blob,
77 magic_number,
78 text_encoder,
79 count_array_header,
80 suffix_array_header,
81 bwm_header,
82 count_array_view,
83 suffix_array_view,
84 bwm_view,
85 })
86 }
87}