1use dejadb_cal::store_types::GrainTypeDiversityConfig;
8use dejadb_core::types::GrainType;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum OutputFormat {
14 Sml,
16 Toon,
18 Markdown,
20 PlainText,
22 Json,
24}
25
26#[derive(Debug, Clone, Copy, PartialEq)]
28pub enum MetadataLevel {
29 None,
31 Minimal,
33 Full,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq)]
40pub enum Ordering {
41 ByRelevance,
43 Chronological,
45 ReverseChronological,
47 ByEntity,
49}
50
51#[derive(Debug, Clone, Default)]
53pub struct SectionConfig {
54 pub group_by_type: bool,
56 pub type_order: Vec<GrainType>,
60}
61
62#[derive(Debug, Clone)]
64pub struct GrainTypeOverride {
65 pub include: bool,
67 pub max_count: Option<usize>,
69}
70
71impl Default for GrainTypeOverride {
72 fn default() -> Self {
73 Self {
74 include: true,
75 max_count: None,
76 }
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct FormatPolicy {
83 pub format: OutputFormat,
84 pub metadata: MetadataLevel,
85 pub ordering: Ordering,
86 pub sections: SectionConfig,
87 pub token_budget: Option<usize>,
88 pub grain_overrides: HashMap<GrainType, GrainTypeOverride>,
89 pub query_text: Option<String>,
93 pub grain_type_diversity: Option<GrainTypeDiversityConfig>,
97}
98
99impl FormatPolicy {
100 pub fn new(format: OutputFormat) -> Self {
101 Self {
102 format,
103 metadata: MetadataLevel::Minimal,
104 ordering: Ordering::ByRelevance,
105 sections: SectionConfig::default(),
106 token_budget: None,
107 grain_overrides: HashMap::new(),
108 query_text: None,
109 grain_type_diversity: Some(GrainTypeDiversityConfig::default()),
110 }
111 }
112
113 pub fn metadata(mut self, level: MetadataLevel) -> Self {
114 self.metadata = level;
115 self
116 }
117
118 pub fn ordering(mut self, ordering: Ordering) -> Self {
119 self.ordering = ordering;
120 self
121 }
122
123 pub fn token_budget(mut self, budget: usize) -> Self {
124 self.token_budget = Some(budget);
125 self
126 }
127
128 pub fn group_by_type(mut self) -> Self {
129 self.sections.group_by_type = true;
130 self
131 }
132
133 pub fn grain_override(mut self, gt: GrainType, ovr: GrainTypeOverride) -> Self {
134 self.grain_overrides.insert(gt, ovr);
135 self
136 }
137
138 pub fn query_text(mut self, text: impl Into<String>) -> Self {
140 self.query_text = Some(text.into());
141 self
142 }
143
144 pub fn grain_type_diversity(mut self, config: GrainTypeDiversityConfig) -> Self {
146 self.grain_type_diversity = Some(config);
147 self
148 }
149
150 pub fn no_grain_type_diversity(mut self) -> Self {
152 self.grain_type_diversity = None;
153 self
154 }
155}
156
157impl Default for FormatPolicy {
158 fn default() -> Self {
159 Self::new(OutputFormat::PlainText)
160 .metadata(MetadataLevel::Minimal)
161 .ordering(Ordering::ByRelevance)
162 }
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168
169 #[test]
170 fn test_default_policy() {
171 let p = FormatPolicy::default();
172 assert_eq!(p.format, OutputFormat::PlainText);
173 assert_eq!(p.metadata, MetadataLevel::Minimal);
174 assert_eq!(p.ordering, Ordering::ByRelevance);
175 assert!(p.token_budget.is_none());
176 assert!(!p.sections.group_by_type);
177 }
178
179 #[test]
180 fn test_builder_chain() {
181 let p = FormatPolicy::new(OutputFormat::Sml)
182 .metadata(MetadataLevel::Full)
183 .ordering(Ordering::Chronological)
184 .token_budget(4096)
185 .group_by_type()
186 .grain_override(
187 GrainType::Consent,
188 GrainTypeOverride {
189 include: true,
190 max_count: Some(5),
191 },
192 );
193
194 assert_eq!(p.format, OutputFormat::Sml);
195 assert_eq!(p.metadata, MetadataLevel::Full);
196 assert_eq!(p.ordering, Ordering::Chronological);
197 assert_eq!(p.token_budget, Some(4096));
198 assert!(p.sections.group_by_type);
199 assert_eq!(
200 p.grain_overrides
201 .get(&GrainType::Consent)
202 .unwrap()
203 .max_count,
204 Some(5)
205 );
206 }
207}