1mod run;
8
9pub use run::{ReportFile, ReportHost, UseEnd, run};
10
11use crate::lir::{ConstId, ExprId, PlaceId};
12use crate::vocab::Pos;
13use crate::{codec_enum, codec_struct};
14
15pub mod state {
17 pub const INITIATED: usize = 0;
18 pub const GENERATED: usize = 1;
19 pub const STARTED: usize = 2;
21 pub const HEADING_DUE: usize = 3;
23 pub const BODY_ON_PAGE: usize = 4;
24 pub const HEADING_ONLY: usize = 5;
26 pub const VERTICAL: usize = 8;
28 pub const SAVED_NEXT_GROUP: usize = 12;
30 pub const FLAGS: usize = 16;
32}
33
34#[derive(Clone, Copy, Debug, PartialEq, Eq)]
36pub enum Footing {
37 Line(u32),
38 Plus(u32),
39}
40
41#[derive(Clone, Copy, Debug, PartialEq, Eq)]
42pub enum NextGroup {
43 Line(u32),
44 Plus(u32),
45 NextPage,
46}
47
48#[derive(Clone, Copy, Debug, PartialEq, Eq)]
49pub enum LineNumber {
50 Line(u32),
51 Plus(u32),
52 NextPage(Option<u32>),
54}
55
56#[derive(Clone, Copy, Debug, PartialEq, Eq)]
57pub enum ColumnNumber {
58 Left(u32),
59 Plus(u32),
60 Right(u32),
61 Center(u32),
62}
63
64#[derive(Clone, Copy, Debug, PartialEq, Eq)]
67pub enum ReportOp {
68 Initiate(u32),
69 Generate { report: u32, detail: Option<u32> },
70 Terminate(u32),
71 Suppress,
72}
73
74#[derive(Clone, Debug, PartialEq, Eq)]
76pub struct Writer<X = ExprId, C = PlaceId, V = ConstId> {
77 pub reports: Vec<Report<X, C, V>>,
78 pub print_switch: Option<usize>,
80}
81
82impl<X, C, V> Default for Writer<X, C, V> {
83 fn default() -> Self {
84 Writer { reports: Vec::new(), print_switch: None }
85 }
86}
87
88#[derive(Clone, Debug, PartialEq, Eq)]
89pub struct Report<X = ExprId, C = PlaceId, V = ConstId> {
90 pub name: String,
91 pub file: usize,
92 pub code: Option<V>,
93 pub width: usize,
95 pub page: Option<Page>,
96 pub controls: Vec<Control<C>>,
98 pub groups: Vec<Group<X, V>>,
99 pub sums: Vec<Sum>,
100 pub subtotals: Vec<Subtotal<X>>,
102 pub page_counter: usize,
103 pub line_counter: usize,
104 pub state: usize,
105 pub report_heading: Option<usize>,
106 pub page_heading: Option<usize>,
107 pub page_footing: Option<usize>,
108 pub report_footing: Option<usize>,
109 pub control_headings: Vec<Option<usize>>,
111 pub control_footings: Vec<Option<usize>>,
112 pub first_detail_written: Option<i64>,
114}
115
116#[derive(Clone, Copy, Debug, PartialEq, Eq)]
118pub struct Page {
119 pub limit: i64,
120 pub heading: i64,
121 pub first_detail: i64,
122 pub last_detail: i64,
123 pub footing: i64,
124}
125
126#[derive(Clone, Debug, PartialEq, Eq)]
127pub struct Control<C = PlaceId> {
128 pub reference: C,
129 pub saved: usize,
131 pub len: usize,
132}
133
134#[derive(Clone, Copy, Debug, PartialEq, Eq)]
135pub enum GroupKind {
136 ReportHeading,
137 PageHeading,
138 ControlHeading,
139 Detail,
140 ControlFooting,
141 PageFooting,
142 ReportFooting,
143}
144
145impl GroupKind {
146 pub fn is_body(self) -> bool {
147 matches!(self, Self::ControlHeading | Self::Detail | Self::ControlFooting)
148 }
149}
150
151#[derive(Clone, Debug, PartialEq, Eq)]
152pub struct Group<X = ExprId, V = ConstId> {
153 pub name: Option<String>,
154 pub kind: GroupKind,
155 pub level: usize,
157 pub next_group: Option<NextGroup>,
158 pub lines: Vec<Line<X, V>>,
159 pub unprinted: Vec<Field<X, V>>,
161 pub cross: Vec<(usize, Origin<X, V>)>,
163 pub rolls: Vec<(usize, Origin<X, V>)>,
165 pub totals: Vec<usize>,
167 pub indicate: Option<usize>,
168 pub declarative: Option<(usize, usize)>,
170}
171
172#[derive(Clone, Debug, PartialEq, Eq)]
173pub struct Line<X = ExprId, V = ConstId> {
174 pub number: LineNumber,
175 pub fields: Vec<Field<X, V>>,
176}
177
178#[derive(Clone, Debug, PartialEq, Eq)]
179pub struct Field<X = ExprId, V = ConstId> {
180 pub item: usize,
181 pub column: usize,
183 pub content: FieldContent<X, V>,
184 pub group_indicate: bool,
185 pub blank_when_zero: bool,
187 pub rounded: bool,
188 pub pos: Pos,
189}
190
191#[derive(Clone, Debug, PartialEq, Eq)]
192pub enum FieldContent<X = ExprId, V = ConstId> {
193 Source(X),
194 Value(V),
195 Sum(usize),
196 Program,
198}
199
200#[derive(Clone, Debug, PartialEq, Eq)]
201pub struct Sum {
202 pub total: usize,
203 pub reset: Option<usize>,
205}
206
207#[derive(Clone, Debug, PartialEq, Eq)]
209pub enum Origin<X = ExprId, V = ConstId> {
210 Source(X),
211 Value(V),
212 Total(usize),
213}
214
215#[derive(Clone, Debug, PartialEq, Eq)]
216pub struct Subtotal<X = ExprId> {
217 pub sum: usize,
218 pub operand: X,
219 pub adding: Adding,
220}
221
222#[derive(Clone, Debug, PartialEq, Eq)]
223pub enum Adding {
224 EveryGenerate,
225 Upon(Vec<usize>),
227 Correlated(Vec<usize>),
229}
230
231pub fn span<X, V>(g: &Group<X, V>) -> i64 {
233 g.lines.iter().map(|l| if let LineNumber::Plus(k) = l.number { k as i64 } else { 0 }).sum()
234}
235
236pub fn generate_target<X, C, V>(reports: &[Report<X, C, V>], name: &str, qualifier: Option<&str>) -> Option<(usize, Option<usize>)> {
238 if qualifier.is_none()
239 && let Some(ri) = reports.iter().position(|r| r.name == name)
240 {
241 return Some((ri, None));
242 }
243 let mut found = reports
244 .iter()
245 .enumerate()
246 .filter(|(_, r)| qualifier.is_none_or(|q| r.name == q))
247 .flat_map(|(ri, r)| r.groups.iter().enumerate().filter(|(_, g)| g.kind == GroupKind::Detail && g.name.as_deref() == Some(name)).map(move |(gi, _)| (ri, Some(gi))));
248 let first = found.next()?;
249 found.next().is_none().then_some(first)
250}
251
252codec_enum!(ReportOp { Initiate(report) = 0, Generate { report, detail } = 1, Terminate(report) = 2, Suppress = 3 });
253codec_enum!(NextGroup { Line(line) = 0, Plus(lines) = 1, NextPage = 2 });
254codec_enum!(LineNumber { Line(line) = 0, Plus(lines) = 1, NextPage(line) = 2 });
255codec_struct!(Writer { reports, print_switch });
256codec_struct!(Report {
257 name, file, code, width, page, controls, groups, sums, subtotals, page_counter, line_counter, state, report_heading,
258 page_heading, page_footing, report_footing, control_headings, control_footings, first_detail_written,
259});
260codec_struct!(Page { limit, heading, first_detail, last_detail, footing });
261codec_struct!(Control { reference, saved, len });
262codec_enum!(GroupKind {
263 ReportHeading = 0,
264 PageHeading = 1,
265 ControlHeading = 2,
266 Detail = 3,
267 ControlFooting = 4,
268 PageFooting = 5,
269 ReportFooting = 6,
270});
271codec_struct!(Group { name, kind, level, next_group, lines, unprinted, cross, rolls, totals, indicate, declarative });
272codec_struct!(Line { number, fields });
273codec_struct!(Field { item, column, content, group_indicate, blank_when_zero, rounded, pos });
274codec_enum!(FieldContent { Source(expr) = 0, Value(value) = 1, Sum(sum) = 2, Program = 3 });
275codec_struct!(Sum { total, reset });
276codec_enum!(Origin { Source(expr) = 0, Value(value) = 1, Total(sum) = 2 });
277codec_struct!(Subtotal { sum, operand, adding });
278codec_enum!(Adding { EveryGenerate = 0, Upon(details) = 1, Correlated(details) = 2 });