1use serde::{Deserialize, Serialize};
4
5use super::encoding::Encoding;
6use super::format::{BoundaryRule, ChunkingSpec, NodeLayoutSpec, TreeFormat};
7
8#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
10pub struct RuntimeConfig {
11 pub node_cache_max_nodes: Option<usize>,
13 pub node_cache_max_bytes: Option<usize>,
15 pub read_parallelism: usize,
17}
18
19impl Default for RuntimeConfig {
20 fn default() -> Self {
21 Self {
22 node_cache_max_nodes: None,
23 node_cache_max_bytes: None,
24 read_parallelism: 1,
25 }
26 }
27}
28
29#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
31pub struct Config {
32 pub format: TreeFormat,
34 pub runtime: RuntimeConfig,
36}
37
38impl Config {
39 pub fn builder() -> ConfigBuilder {
41 ConfigBuilder::default()
42 }
43
44 pub fn min_chunk_size(&self) -> usize {
46 self.format.chunking.min as usize
47 }
48
49 pub fn max_chunk_size(&self) -> usize {
51 self.format.chunking.max as usize
52 }
53
54 pub fn chunking_factor(&self) -> u32 {
56 match self.format.chunking.rule {
57 BoundaryRule::HashThreshold { factor } => factor,
58 _ => self.format.chunking.target.min(u64::from(u32::MAX)) as u32,
59 }
60 }
61
62 pub fn hash_seed(&self) -> u64 {
64 self.format.chunking.hash_seed
65 }
66
67 pub fn encoding(&self) -> &Encoding {
69 &self.format.value_encoding
70 }
71}
72
73#[derive(Default)]
75pub struct ConfigBuilder {
76 config: Config,
77}
78
79impl ConfigBuilder {
80 pub fn min_chunk_size(mut self, size: usize) -> Self {
82 self.config.format.chunking.min = size as u64;
83 self.config.format.chunking.target = self.config.format.chunking.target.max(size as u64);
84 self.config.format.chunking.max = self.config.format.chunking.max.max(size as u64);
85 self
86 }
87
88 pub fn max_chunk_size(mut self, size: usize) -> Self {
90 self.config.format.chunking.max = size as u64;
91 self.config.format.chunking.target = self.config.format.chunking.target.min(size as u64);
92 self.config.format.chunking.min = self.config.format.chunking.min.min(size as u64);
93 self
94 }
95
96 pub fn chunking_factor(mut self, factor: u32) -> Self {
98 self.config.format.chunking.rule = BoundaryRule::HashThreshold { factor };
99 self
100 }
101
102 pub fn hash_seed(mut self, seed: u64) -> Self {
104 self.config.format.chunking.hash_seed = seed;
105 self
106 }
107
108 pub fn encoding(mut self, encoding: Encoding) -> Self {
110 self.config.format.value_encoding = encoding;
111 self
112 }
113
114 pub fn chunking(mut self, chunking: ChunkingSpec) -> Self {
116 self.config.format.chunking = chunking;
117 self
118 }
119
120 pub fn node_layout(mut self, layout: NodeLayoutSpec) -> Self {
122 self.config.format.node_layout = layout;
123 self
124 }
125
126 pub fn format(mut self, format: TreeFormat) -> Self {
128 self.config.format = format;
129 self
130 }
131
132 pub fn node_cache_max_nodes(mut self, max_nodes: usize) -> Self {
137 self.config.runtime.node_cache_max_nodes = Some(max_nodes);
138 self
139 }
140
141 pub fn node_cache_max_bytes(mut self, max_bytes: usize) -> Self {
146 self.config.runtime.node_cache_max_bytes = Some(max_bytes);
147 self
148 }
149
150 pub fn unbounded_node_cache(mut self) -> Self {
152 self.config.runtime.node_cache_max_nodes = None;
153 self.config.runtime.node_cache_max_bytes = None;
154 self
155 }
156
157 pub fn read_parallelism(mut self, parallelism: usize) -> Self {
159 self.config.runtime.read_parallelism = parallelism.max(1);
160 self
161 }
162
163 pub fn build(self) -> Config {
165 self.config
166 }
167}
168
169#[cfg(test)]
170mod tests {
171 use super::*;
172
173 #[test]
174 fn test_config_default() {
175 let config = Config::default();
176 assert_eq!(config, Config::default());
177 assert_eq!(config.runtime, RuntimeConfig::default());
178 }
179
180 #[test]
181 fn test_config_builder() {
182 let config = Config::builder()
183 .min_chunk_size(2)
184 .max_chunk_size(100)
185 .chunking_factor(64)
186 .hash_seed(42)
187 .encoding(Encoding::Cbor)
188 .node_cache_max_nodes(128)
189 .node_cache_max_bytes(1_048_576)
190 .build();
191
192 assert_eq!(config.min_chunk_size(), 2);
193 assert_eq!(config.max_chunk_size(), 100);
194 assert_eq!(config.chunking_factor(), 64);
195 assert_eq!(config.hash_seed(), 42);
196 assert_eq!(config.encoding(), &Encoding::Cbor);
197 assert_eq!(config.runtime.node_cache_max_nodes, Some(128));
198 assert_eq!(config.runtime.node_cache_max_bytes, Some(1_048_576));
199
200 let config = Config::builder()
201 .node_cache_max_nodes(128)
202 .node_cache_max_bytes(1_048_576)
203 .unbounded_node_cache()
204 .build();
205 assert_eq!(config.runtime.node_cache_max_nodes, None);
206 assert_eq!(config.runtime.node_cache_max_bytes, None);
207 }
208}