1use super::{IntExpr, MovePlan, Operand, PlaceId, RangeId, 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 status: Option<(PlaceId, MovePlan)>,
26 pub keys: Option<IndexKeys>,
28 pub relative: Option<RelativeKey>,
29 pub linage: Option<Linage>,
30 pub carriage: Option<Carriage>,
32 pub sort: bool,
34 pub error: Option<RangeId>,
36}
37
38#[derive(Clone, Copy, Debug, PartialEq, Eq)]
39pub enum Organization {
40 Sequential,
41 LineSequential,
42 Indexed,
43 Relative,
44}
45
46#[derive(Clone, Copy, Debug, PartialEq, Eq)]
47pub enum Access {
48 Sequential,
49 Random,
50 Dynamic,
51}
52
53#[derive(Clone, Copy, Debug, PartialEq, Eq)]
55pub struct RecordSpan {
56 pub offset: u32,
57 pub len: u32,
58}
59
60#[derive(Clone, Debug, PartialEq, Eq)]
63pub struct IndexKeys {
64 pub prime: RecordSpan,
65 pub alternates: Vec<(RecordSpan, bool)>,
66}
67
68#[derive(Clone, Debug, PartialEq, Eq)]
71pub struct RelativeKey {
72 pub place: PlaceId,
73 pub value: IntExpr,
74 pub store: StorePlan,
75 pub digits: Option<u32>,
76}
77
78#[derive(Clone, Debug, PartialEq, Eq)]
81pub struct Linage {
82 pub lines: IntExpr,
83 pub footing: Option<IntExpr>,
84 pub top: Option<IntExpr>,
85 pub bottom: Option<IntExpr>,
86 pub counter: Option<(PlaceId, StorePlan)>,
87}
88
89#[derive(Clone, Copy, Debug, PartialEq, Eq)]
92pub struct Carriage {
93 pub machine: bool,
94 pub reserved: bool,
95}
96
97#[derive(Clone, Debug, PartialEq, Eq)]
103pub struct FileOp {
104 pub file: u16,
105 pub verb: FileVerb,
106 pub phrase: Option<Phrase>,
107 pub end_of_page: Option<Phrase>,
108}
109
110impl FileOp {
111 pub fn arms(&self) -> usize {
113 match (self.phrase, self.end_of_page) {
114 (None, None) => 0,
115 (_, None) => 3,
116 (_, Some(_)) => 5,
117 }
118 }
119}
120
121#[derive(Clone, Copy, Debug, PartialEq, Eq)]
122pub struct Phrase {
123 pub on: bool,
124 pub not_on: bool,
125}
126
127#[derive(Clone, Debug, PartialEq, Eq)]
128pub enum FileVerb {
129 Open(OpenMode),
130 Close,
131 CloseWith(Closing),
132 Read { sequential: bool, previous: bool, into: Option<(PlaceId, MovePlan)>, key: u8 },
135 Write { record: PlaceId, from: Option<FromMove>, advancing: Option<Advance> },
137 Rewrite { record: PlaceId, from: Option<FromMove> },
138 Delete,
139 Start { rel: StartRel, key: StartKey },
140}
141
142#[derive(Clone, Copy, Debug, PartialEq, Eq)]
144pub struct FromMove {
145 pub from: Operand,
146 pub to: PlaceId,
147 pub plan: MovePlan,
148}
149
150#[derive(Clone, Debug, PartialEq, Eq)]
153pub enum Advance {
154 Lines { before: bool, count: IntExpr },
155 Page { before: bool },
156 Mnemonic { before: bool, space: Spacing },
158}
159
160#[derive(Clone, Copy, Debug, PartialEq, Eq)]
161pub enum Spacing {
162 Lines(u64),
164 Channel(u8),
165 PageMode,
167}
168
169#[derive(Clone, Copy, Debug, PartialEq, Eq)]
171pub enum StartRel {
172 Equal,
173 Greater,
174 NotLess,
175}
176
177#[derive(Clone, Debug, PartialEq, Eq)]
178pub enum StartKey {
179 Prime,
181 Named { key: u8, span: RecordSpan },
183 Relative(IntExpr),
185 RelativeKey,
187}
188
189codec_struct!(FileDesc {
190 name, assign, organization, access, optional, format, read_lengths, status, keys, relative, linage, carriage, sort, error,
191} check file_valid);
192codec_enum!(Organization { Sequential = 0, LineSequential = 1, Indexed = 2, Relative = 3 });
193codec_enum!(Access { Sequential = 0, Random = 1, Dynamic = 2 });
194codec_struct!(RecordSpan { offset, len });
195codec_struct!(IndexKeys { prime, alternates });
196codec_struct!(RelativeKey { place, value, store, digits });
197codec_struct!(Linage { lines, footing, top, bottom, counter });
198codec_struct!(Carriage { machine, reserved });
199codec_struct!(FileOp { file, verb, phrase, end_of_page });
200codec_struct!(Phrase { on, not_on });
201codec_enum!(FileVerb {
202 Open(mode) = 0,
203 Close = 1,
204 Read { sequential, previous, into, key } = 2,
205 Write { record, from, advancing } = 3,
206 Rewrite { record, from } = 4,
207 Delete = 5,
208 Start { rel, key } = 6,
209 CloseWith(closing) = 7,
210});
211codec_struct!(FromMove { from, to, plan });
212codec_enum!(Advance { Lines { before, count } = 0, Page { before } = 1, Mnemonic { before, space } = 2 });
213codec_enum!(Spacing { Lines(n) = 0, Channel(c) = 1, PageMode = 2 });
214codec_enum!(StartRel { Equal = 0, Greater = 1, NotLess = 2 });
215codec_enum!(StartKey { Prime = 0, Named { key, span } = 1, Relative(value) = 2, RelativeKey = 3 });
216
217fn file_valid(file: &FileDesc) -> Result<(), String> {
219 if file.keys.is_some() == (file.organization == Organization::Indexed) {
220 Ok(())
221 } else {
222 Err("keys on a file that is not indexed, or an indexed file without them".into())
223 }
224}