1use super::{IntExpr, MovePlan, Operand, PlaceId, RangeId, SenderCheck, StorePlan, SymId};
6use crate::files::Format;
7use crate::vocab::{Closing, OpenMode};
8use crate::{codec_enum, codec_struct};
9
10#[derive(Clone, Debug, PartialEq, Eq)]
13pub struct FileDesc {
14 pub name: SymId,
15 pub assign: SymId,
17 pub organization: Organization,
18 pub access: Access,
19 pub optional: bool,
20 pub format: Format,
21 pub read_lengths: (u32, u32),
25 pub fixed: bool,
27 pub record_min: Option<u32>,
29 pub depending: Option<RecordDepending>,
30 pub status: Option<(PlaceId, MovePlan)>,
31 pub keys: Option<IndexKeys>,
33 pub relative: Option<RelativeKey>,
34 pub linage: Option<Linage>,
35 pub carriage: Option<Carriage>,
37 pub sort: bool,
39 pub error: Option<RangeId>,
41}
42
43#[derive(Clone, Copy, Debug, PartialEq, Eq)]
44pub enum Organization {
45 Sequential,
46 LineSequential,
47 Indexed,
48 Relative,
49}
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq)]
52pub enum Access {
53 Sequential,
54 Random,
55 Dynamic,
56}
57
58#[derive(Clone, Copy, Debug, PartialEq, Eq)]
62pub struct RecordDepending {
63 pub item: PlaceId,
64 pub lengths: (u32, u32),
65}
66
67#[derive(Clone, Copy, Debug, PartialEq, Eq)]
69pub struct RecordSpan {
70 pub offset: u32,
71 pub len: u32,
72}
73
74#[derive(Clone, Debug, PartialEq, Eq)]
77pub struct IndexKeys {
78 pub prime: RecordSpan,
79 pub alternates: Vec<(RecordSpan, bool)>,
80}
81
82#[derive(Clone, Debug, PartialEq, Eq)]
85pub struct RelativeKey {
86 pub place: PlaceId,
87 pub value: IntExpr,
88 pub store: StorePlan,
89 pub digits: Option<u32>,
90}
91
92#[derive(Clone, Debug, PartialEq, Eq)]
95pub struct Linage {
96 pub lines: IntExpr,
97 pub footing: Option<IntExpr>,
98 pub top: Option<IntExpr>,
99 pub bottom: Option<IntExpr>,
100 pub counter: Option<(PlaceId, StorePlan)>,
101}
102
103#[derive(Clone, Copy, Debug, PartialEq, Eq)]
106pub struct Carriage {
107 pub machine: bool,
108 pub reserved: bool,
109}
110
111#[derive(Clone, Debug, PartialEq, Eq)]
117pub struct FileOp {
118 pub file: u16,
119 pub verb: FileVerb,
120 pub phrase: Option<Phrase>,
121 pub end_of_page: Option<Phrase>,
122}
123
124impl FileOp {
125 pub fn arms(&self) -> usize {
127 match (self.phrase, self.end_of_page) {
128 (None, None) => 0,
129 (_, None) => 3,
130 (_, Some(_)) => 5,
131 }
132 }
133}
134
135#[derive(Clone, Copy, Debug, PartialEq, Eq)]
136pub struct Phrase {
137 pub on: bool,
138 pub not_on: bool,
139}
140
141#[derive(Clone, Debug, PartialEq, Eq)]
142pub enum FileVerb {
143 Open(OpenMode),
144 Close,
145 CloseWith(Closing),
146 Read { sequential: bool, previous: bool, into: Option<(PlaceId, MovePlan)>, key: u8 },
149 Write { record: PlaceId, from: Option<FromMove>, advancing: Option<Advance> },
151 Rewrite { record: PlaceId, from: Option<FromMove> },
152 Delete,
153 Start { rel: StartRel, key: StartKey },
154}
155
156#[derive(Clone, Copy, Debug, PartialEq, Eq)]
159pub struct FromMove {
160 pub from: Operand,
161 pub to: PlaceId,
162 pub plan: MovePlan,
163 pub check: SenderCheck,
164}
165
166#[derive(Clone, Debug, PartialEq, Eq)]
169pub enum Advance {
170 Lines { before: bool, count: IntExpr },
171 Page { before: bool },
172 Mnemonic { before: bool, space: Spacing },
174}
175
176#[derive(Clone, Copy, Debug, PartialEq, Eq)]
177pub enum Spacing {
178 Lines(u64),
180 Channel(u8),
181 PageMode,
183}
184
185#[derive(Clone, Copy, Debug, PartialEq, Eq)]
187pub enum StartRel {
188 Equal,
189 Greater,
190 NotLess,
191}
192
193#[derive(Clone, Debug, PartialEq, Eq)]
194pub enum StartKey {
195 Prime,
197 Named { key: u8, span: RecordSpan },
199 Relative(IntExpr),
201 RelativeKey,
203}
204
205codec_struct!(FileDesc {
206 name, assign, organization, access, optional, format, read_lengths, fixed, record_min, depending, status, keys, relative, linage, carriage, sort, error,
207} check file_valid);
208codec_struct!(RecordDepending { item, lengths });
209codec_enum!(Organization { Sequential = 0, LineSequential = 1, Indexed = 2, Relative = 3 });
210codec_enum!(Access { Sequential = 0, Random = 1, Dynamic = 2 });
211codec_struct!(RecordSpan { offset, len });
212codec_struct!(IndexKeys { prime, alternates });
213codec_struct!(RelativeKey { place, value, store, digits });
214codec_struct!(Linage { lines, footing, top, bottom, counter });
215codec_struct!(Carriage { machine, reserved });
216codec_struct!(FileOp { file, verb, phrase, end_of_page });
217codec_struct!(Phrase { on, not_on });
218codec_enum!(FileVerb {
219 Open(mode) = 0,
220 Close = 1,
221 Read { sequential, previous, into, key } = 2,
222 Write { record, from, advancing } = 3,
223 Rewrite { record, from } = 4,
224 Delete = 5,
225 Start { rel, key } = 6,
226 CloseWith(closing) = 7,
227});
228codec_struct!(FromMove { from, to, plan, check });
229codec_enum!(Advance { Lines { before, count } = 0, Page { before } = 1, Mnemonic { before, space } = 2 });
230codec_enum!(Spacing { Lines(n) = 0, Channel(c) = 1, PageMode = 2 });
231codec_enum!(StartRel { Equal = 0, Greater = 1, NotLess = 2 });
232codec_enum!(StartKey { Prime = 0, Named { key, span } = 1, Relative(value) = 2, RelativeKey = 3 });
233
234fn file_valid(file: &FileDesc) -> Result<(), String> {
236 if file.keys.is_some() == (file.organization == Organization::Indexed) {
237 Ok(())
238 } else {
239 Err("keys on a file that is not indexed, or an indexed file without them".into())
240 }
241}