fmf_core\engine/
results.rs1use std::sync::Arc;
2
3use crate::index::{EntryId, VolumeIndex, flags};
4
5use super::EngineError;
6use super::volume::VolumeSlot;
7
8pub struct Row {
10 pub entry_ref: u64,
12 pub frn: u64,
14 pub size: u64,
16 pub mtime: i64,
18 pub flags: u32,
20 pub name: Vec<u8>,
22 pub parent_path: Vec<u8>,
24}
25
26pub struct ResultSet {
30 pub(super) slots: Vec<Arc<VolumeSlot>>,
31 pub(super) structural: Vec<u64>,
32 pub(super) rows: Vec<(u32, EntryId)>,
33}
34
35impl ResultSet {
36 #[must_use]
38 pub const fn len(&self) -> usize {
39 self.rows.len()
40 }
41
42 #[must_use]
44 pub const fn is_empty(&self) -> bool {
45 self.rows.is_empty()
46 }
47
48 pub fn fill_page(
59 &self,
60 offset: usize,
61 count: usize,
62 ) -> Result<(Vec<fmf_contract::pod::FmfRow>, Vec<u8>), EngineError> {
63 let rows_data = self.page(offset, count)?;
64 let mut blob = Vec::new();
65 let mut rows = Vec::with_capacity(rows_data.len());
66 for row in &rows_data {
67 let name_off = blob.len() as u32;
68 blob.extend_from_slice(&row.name);
69 let parent_off = blob.len() as u32;
70 blob.extend_from_slice(&row.parent_path);
71 rows.push(fmf_contract::pod::FmfRow {
72 entry_ref: row.entry_ref,
73 frn: row.frn,
74 size: row.size,
75 mtime: row.mtime,
76 name_off,
77 parent_path_off: parent_off,
78 flags: row.flags,
79 name_len: row.name.len() as u16,
80 parent_path_len: row.parent_path.len() as u16,
81 });
82 }
83 Ok((rows, blob))
84 }
85
86 pub fn page(&self, offset: usize, count: usize) -> Result<Vec<Row>, EngineError> {
93 let end = (offset.saturating_add(count)).min(self.rows.len());
94 let start = offset.min(end);
95 let mut out = Vec::with_capacity(end - start);
96
97 let guards: Vec<_> = self.slots.iter().map(|s| s.index.read()).collect();
98 for (v, guard) in guards.iter().enumerate() {
99 let idx = guard.as_ref().ok_or(EngineError::Stale)?;
100 if idx.structural_generation() != self.structural[v] {
101 return Err(EngineError::Stale);
102 }
103 }
104 for &(v, id) in &self.rows[start..end] {
105 let idx = guards[v as usize].as_ref().ok_or(EngineError::Stale)?;
106 let mut parent_path = Vec::new();
107 idx.append_parent_path(id, &mut parent_path);
108 out.push(Row {
109 entry_ref: ((v as u64) << 32) | id as u64,
110 frn: idx.frn(id).0,
111 size: idx.size(id),
112 mtime: idx.mtime(id),
113 flags: idx_flags(idx, id),
114 name: idx.name(id).to_vec(),
115 parent_path,
116 });
117 }
118 Ok(out)
119 }
120}
121
122fn idx_flags(idx: &VolumeIndex, id: EntryId) -> u32 {
123 let mut f = 0u32;
124 if idx.is_dir(id) {
125 f |= 1;
126 }
127 if !idx.is_live(id) {
128 f |= 2; }
130 f
131}
132
133const _: () = {
135 assert!(flags::IS_DIR == 1);
136};