use super::{IntExpr, MovePlan, Operand, PlaceId, RangeId, SenderCheck, StorePlan, SymId};
use crate::files::Format;
use crate::vocab::{Closing, OpenMode};
use crate::{codec_enum, codec_struct};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FileDesc {
pub name: SymId,
pub assign: SymId,
pub organization: Organization,
pub access: Access,
pub optional: bool,
pub format: Format,
pub read_lengths: (u32, u32),
pub fixed: bool,
pub record_min: Option<u32>,
pub depending: Option<RecordDepending>,
pub status: Option<(PlaceId, MovePlan)>,
pub keys: Option<IndexKeys>,
pub relative: Option<RelativeKey>,
pub linage: Option<Linage>,
pub carriage: Option<Carriage>,
pub sort: bool,
pub error: Option<RangeId>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Organization {
Sequential,
LineSequential,
Indexed,
Relative,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Access {
Sequential,
Random,
Dynamic,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RecordDepending {
pub item: PlaceId,
pub lengths: (u32, u32),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct RecordSpan {
pub offset: u32,
pub len: u32,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct IndexKeys {
pub prime: RecordSpan,
pub alternates: Vec<(RecordSpan, bool)>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct RelativeKey {
pub place: PlaceId,
pub value: IntExpr,
pub store: StorePlan,
pub digits: Option<u32>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Linage {
pub lines: IntExpr,
pub footing: Option<IntExpr>,
pub top: Option<IntExpr>,
pub bottom: Option<IntExpr>,
pub counter: Option<(PlaceId, StorePlan)>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Carriage {
pub machine: bool,
pub reserved: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FileOp {
pub file: u16,
pub verb: FileVerb,
pub phrase: Option<Phrase>,
pub end_of_page: Option<Phrase>,
}
impl FileOp {
pub fn arms(&self) -> usize {
match (self.phrase, self.end_of_page) {
(None, None) => 0,
(_, None) => 3,
(_, Some(_)) => 5,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct Phrase {
pub on: bool,
pub not_on: bool,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FileVerb {
Open(OpenMode),
Close,
CloseWith(Closing),
Read { sequential: bool, previous: bool, into: Option<(PlaceId, MovePlan)>, key: u8 },
Write { record: PlaceId, from: Option<FromMove>, advancing: Option<Advance> },
Rewrite { record: PlaceId, from: Option<FromMove> },
Delete,
Start { rel: StartRel, key: StartKey },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct FromMove {
pub from: Operand,
pub to: PlaceId,
pub plan: MovePlan,
pub check: SenderCheck,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Advance {
Lines { before: bool, count: IntExpr },
Page { before: bool },
Mnemonic { before: bool, space: Spacing },
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Spacing {
Lines(u64),
Channel(u8),
PageMode,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum StartRel {
Equal,
Greater,
NotLess,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum StartKey {
Prime,
Named { key: u8, span: RecordSpan },
Relative(IntExpr),
RelativeKey,
}
codec_struct!(FileDesc {
name, assign, organization, access, optional, format, read_lengths, fixed, record_min, depending, status, keys, relative, linage, carriage, sort, error,
} check file_valid);
codec_struct!(RecordDepending { item, lengths });
codec_enum!(Organization { Sequential = 0, LineSequential = 1, Indexed = 2, Relative = 3 });
codec_enum!(Access { Sequential = 0, Random = 1, Dynamic = 2 });
codec_struct!(RecordSpan { offset, len });
codec_struct!(IndexKeys { prime, alternates });
codec_struct!(RelativeKey { place, value, store, digits });
codec_struct!(Linage { lines, footing, top, bottom, counter });
codec_struct!(Carriage { machine, reserved });
codec_struct!(FileOp { file, verb, phrase, end_of_page });
codec_struct!(Phrase { on, not_on });
codec_enum!(FileVerb {
Open(mode) = 0,
Close = 1,
Read { sequential, previous, into, key } = 2,
Write { record, from, advancing } = 3,
Rewrite { record, from } = 4,
Delete = 5,
Start { rel, key } = 6,
CloseWith(closing) = 7,
});
codec_struct!(FromMove { from, to, plan, check });
codec_enum!(Advance { Lines { before, count } = 0, Page { before } = 1, Mnemonic { before, space } = 2 });
codec_enum!(Spacing { Lines(n) = 0, Channel(c) = 1, PageMode = 2 });
codec_enum!(StartRel { Equal = 0, Greater = 1, NotLess = 2 });
codec_enum!(StartKey { Prime = 0, Named { key, span } = 1, Relative(value) = 2, RelativeKey = 3 });
fn file_valid(file: &FileDesc) -> Result<(), String> {
if file.keys.is_some() == (file.organization == Organization::Indexed) {
Ok(())
} else {
Err("keys on a file that is not indexed, or an indexed file without them".into())
}
}