appcore_filemaker/
table_dataset.rs1use std::collections::BTreeMap;
14
15use serde::{Deserialize, Serialize};
16
17use super::table_error;
18use crate::{DataValue, Result};
19
20pub type DataRow = BTreeMap<String, DataValue>;
22
23pub trait Dataset: Send + Sync {
25 fn row_count_hint(&self) -> Option<u64>;
27 fn visit_rows_until(
29 &self,
30 visitor: &mut dyn FnMut(u64, &DataRow) -> Result<bool>,
31 ) -> Result<()>;
32
33 fn visit_rows(&self, visitor: &mut dyn FnMut(u64, &DataRow) -> Result<()>) -> Result<()> {
35 self.visit_rows_until(&mut |index, row| {
36 visitor(index, row)?;
37 Ok(true)
38 })
39 }
40}
41
42#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
44pub struct InMemoryDataset {
45 pub rows: Vec<DataRow>,
47}
48
49pub struct BorrowedDataset<'a> {
51 rows: &'a [DataRow],
52}
53
54impl<'a> BorrowedDataset<'a> {
55 #[must_use]
57 pub const fn new(rows: &'a [DataRow]) -> Self {
58 Self { rows }
59 }
60}
61
62impl Dataset for BorrowedDataset<'_> {
63 fn row_count_hint(&self) -> Option<u64> {
64 u64::try_from(self.rows.len()).ok()
65 }
66
67 fn visit_rows_until(
68 &self,
69 visitor: &mut dyn FnMut(u64, &DataRow) -> Result<bool>,
70 ) -> Result<()> {
71 visit_slice(self.rows, visitor)
72 }
73}
74
75impl Dataset for InMemoryDataset {
76 fn row_count_hint(&self) -> Option<u64> {
77 u64::try_from(self.rows.len()).ok()
78 }
79
80 fn visit_rows_until(
81 &self,
82 visitor: &mut dyn FnMut(u64, &DataRow) -> Result<bool>,
83 ) -> Result<()> {
84 visit_slice(&self.rows, visitor)
85 }
86}
87
88fn visit_slice(
89 rows: &[DataRow],
90 visitor: &mut dyn FnMut(u64, &DataRow) -> Result<bool>,
91) -> Result<()> {
92 for (index, row) in rows.iter().enumerate() {
93 let index = u64::try_from(index).map_err(|_| table_error("row index overflow"))?;
94 if !visitor(index, row)? {
95 break;
96 }
97 }
98 Ok(())
99}
100
101pub struct StreamingDataset<F> {
103 factory: F,
104 row_count_hint: Option<u64>,
105}
106
107impl<F> StreamingDataset<F> {
108 #[must_use]
110 pub const fn new(factory: F, row_count_hint: Option<u64>) -> Self {
111 Self {
112 factory,
113 row_count_hint,
114 }
115 }
116}
117
118impl<F, I> Dataset for StreamingDataset<F>
119where
120 F: Fn() -> I + Send + Sync,
121 I: Iterator<Item = Result<DataRow>>,
122{
123 fn row_count_hint(&self) -> Option<u64> {
124 self.row_count_hint
125 }
126
127 fn visit_rows_until(
128 &self,
129 visitor: &mut dyn FnMut(u64, &DataRow) -> Result<bool>,
130 ) -> Result<()> {
131 for (index, row) in (self.factory)().enumerate() {
132 let row = row?;
133 if !visitor(
134 u64::try_from(index).map_err(|_| table_error("row index overflow"))?,
135 &row,
136 )? {
137 break;
138 }
139 }
140 Ok(())
141 }
142}