1use std::sync::Arc;
5
6use futures::FutureExt;
7use vortex_buffer::ByteBuffer;
8use vortex_error::{VortexExpect, VortexResult, vortex_bail, vortex_err};
9use vortex_layout::segments::{SegmentFuture, SegmentId, SegmentSource};
10
11use crate::{FileType, Footer, VortexFile, VortexOpenOptions};
12
13pub struct InMemoryFileType;
18
19impl FileType for InMemoryFileType {
20 type Options = ();
21}
22
23impl VortexOpenOptions<InMemoryFileType> {
24 pub fn in_memory() -> Self {
26 Self::new(())
27 }
28
29 pub fn open<B: Into<ByteBuffer>>(self, buffer: B) -> VortexResult<VortexFile> {
31 let buffer = buffer.into();
32
33 let postscript = self.parse_postscript(&buffer)?;
34
35 let dtype = self.dtype
37 .clone()
38 .map(Ok)
39 .unwrap_or_else(|| {
40 let dtype_segment = postscript
41 .dtype
42 .ok_or_else(|| vortex_err!("Vortex file doesn't embed a DType and one has not been provided to VortexOpenOptions"))?;
43 self.parse_dtype(0, &buffer, &dtype_segment)
44 })?;
45
46 let file_stats = postscript
47 .statistics
48 .map(|segment| self.parse_file_statistics(0, &buffer, &segment))
49 .transpose()?;
50
51 let footer = self.parse_footer(
52 0,
53 &buffer,
54 &postscript.footer,
55 &postscript.layout,
56 dtype,
57 file_stats,
58 )?;
59
60 let segment_source = Arc::new(InMemorySegmentReader {
61 buffer,
62 footer: footer.clone(),
63 });
64
65 Ok(VortexFile {
66 footer,
67 segment_source,
68 metrics: self.metrics,
69 })
70 }
71}
72
73#[derive(Clone)]
74struct InMemorySegmentReader {
75 buffer: ByteBuffer,
76 footer: Footer,
77}
78
79impl SegmentSource for InMemorySegmentReader {
80 fn request(&self, id: SegmentId) -> SegmentFuture {
81 let Some(spec) = self.footer.segment_map().get(*id as usize) else {
82 return async move { vortex_bail!("segment not found {id}") }.boxed();
83 };
84
85 let start = usize::try_from(spec.offset).vortex_expect("segment offset larger than usize");
86 let end = start + spec.length as usize;
87 let buffer = self.buffer.slice(start..end);
88
89 async move { Ok(buffer) }.boxed()
90 }
91}