use lalrpop_util::lalrpop_mod;
use std::fs::File;
use std::io::prelude::*;
use std::io::{self, BufReader};
use std::str::FromStr;
use std::fmt;
use std::collections::HashMap;
use std::ops::Index;
lalrpop_mod!(pub xtrakcad);
pub type Spanned<Tok, Loc, Error> = Result<(Loc, Tok, Loc), Error>;
#[derive(Clone, Debug)]
pub enum Tok {
EOL,
DOT,
STRINGTOEOL(String),
NULL,
STRING(String),
UINTEGER(u32),
FLOAT(f64),
A,
ADJUSTABLE,
ASPECT,
B,
BEZIER,
BLOCK,
BZRLIN,
C,
CAR,
CONTROL,
CORNU,
CURRENT,
CURVE,
D,
DRAW,
E,
ENDBLOCK,
ENDSEGS,
ENDSIGNAL,
ENDTRACKS,
F,
G,
H,
HO,
J,
JOINT,
L,
LAYERS,
M,
MAIN,
MAPSCALE,
N,
NOTE,
O,
P,
PIER,
Q,
ROOMSIZE,
S,
SCALE,
SENSOR,
SIGNAL,
STRAIGHT,
STRUCTURE,
SUBSEGS,
SUBSEND,
SWITCHMOTOR,
T,
TEXT,
TITLE,
TRK,
TURNOUT,
TURNTABLE,
VERSION,
W,
X,
Y,
Z,
}
impl fmt::Display for Tok {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Tok::EOL => write!(f,"\\n" ),
Tok::DOT => write!(f,"." ),
Tok::STRINGTOEOL(s) => write!(f,"Tok::STRINGTOEOL({})",s ),
Tok::NULL => write!(f,"Tok::NULL" ),
Tok::STRING(s) => write!(f,"STRING({})", s),
Tok::UINTEGER(u) => write!(f,"UINTEGER({})",u ),
Tok::FLOAT(flo) => write!(f,"FLOAT({})", flo ),
Tok::A => write!(f,"A" ),
Tok::ADJUSTABLE => write!(f,"ADJUSTABLE" ),
Tok::ASPECT => write!(f,"ASPECT" ),
Tok::B => write!(f,"B" ),
Tok::BEZIER => write!(f,"BEZIER" ),
Tok::BLOCK => write!(f,"BLOCK" ),
Tok::BZRLIN => write!(f,"BZRLIN" ),
Tok::C => write!(f,"C" ),
Tok::CAR => write!(f,"CAR" ),
Tok::CONTROL => write!(f,"CONTROL" ),
Tok::CORNU => write!(f,"CORNU" ),
Tok::CURRENT => write!(f,"CURRENT" ),
Tok::CURVE => write!(f,"CURVE" ),
Tok::D => write!(f,"D" ),
Tok::DRAW => write!(f,"DRAW" ),
Tok::E => write!(f,"E" ),
Tok::ENDBLOCK => write!(f,"ENDBLOCK" ),
Tok::ENDSEGS => write!(f,"ENDSEGS" ),
Tok::ENDSIGNAL => write!(f,"ENDSIGNAL" ),
Tok::ENDTRACKS => write!(f,"ENDTRACKS" ),
Tok::F => write!(f,"F" ),
Tok::G => write!(f,"G" ),
Tok::H => write!(f,"H" ),
Tok::HO => write!(f,"HO" ),
Tok::J => write!(f,"J" ),
Tok::JOINT => write!(f,"JOINT" ),
Tok::L => write!(f,"L" ),
Tok::LAYERS => write!(f,"LAYERS" ),
Tok::M => write!(f,"M" ),
Tok::MAIN => write!(f,"MAIN" ),
Tok::MAPSCALE => write!(f,"MAPSCALE" ),
Tok::N => write!(f,"N" ),
Tok::NOTE => write!(f,"NOTE" ),
Tok::O => write!(f,"O" ),
Tok::P => write!(f,"P" ),
Tok::PIER => write!(f,"PIER" ),
Tok::Q => write!(f,"Q" ),
Tok::ROOMSIZE => write!(f,"ROOMSIZE" ),
Tok::S => write!(f,"S" ),
Tok::SCALE => write!(f,"SCALE" ),
Tok::SENSOR => write!(f,"SENSOR" ),
Tok::SIGNAL => write!(f,"SIGNAL" ),
Tok::STRAIGHT => write!(f,"STRAIGHT" ),
Tok::STRUCTURE => write!(f,"STRUCTURE" ),
Tok::SUBSEGS => write!(f,"SUBSEGS" ),
Tok::SUBSEND => write!(f,"SUBSEND" ),
Tok::SWITCHMOTOR => write!(f,"SWITCHMOTOR" ),
Tok::T => write!(f,"T" ),
Tok::TEXT => write!(f,"TEXT" ),
Tok::TITLE => write!(f,"TITLE" ),
Tok::TRK => write!(f,"TRK" ),
Tok::TURNOUT => write!(f,"TURNOUT" ),
Tok::TURNTABLE => write!(f,"TURNTABLE" ),
Tok::VERSION => write!(f,"VERSION" ),
Tok::W => write!(f,"W" ),
Tok::X => write!(f,"X" ),
Tok::Y => write!(f,"Y" ),
Tok::Z => write!(f,"Z" ),
}
}
}
impl Tok {
pub fn StringValue(self) -> String {
match self {
Tok::STRING(s) |
Tok::STRINGTOEOL(s) => s,
_ => String::new(),
}
}
pub fn U32Value(self) -> u32 {
match self {
Tok::UINTEGER(u) => u,
_ => 0,
}
}
pub fn F64Value(self) -> f64 {
match self {
Tok::FLOAT(f) => f,
_ => 0.0,
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum LexicalError {
UnTerminatedString,
UnknownKeyword(String),
IOError(String),
UnknownCharacter(char),
}
impl fmt::Display for LexicalError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LexicalError::UnTerminatedString => write!(f, "Lexical Error: unterminated string"),
LexicalError::UnknownKeyword(word) => write!(f, "Lexical Error: unknown keyword: {}",word),
LexicalError::IOError(message) =>
write!(f, "Lexical Error: error reading file: {}",message),
LexicalError::UnknownCharacter(ch) =>
write!(f, "Lexical Error: unknown character: {}",ch),
}
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum ScanEOL {
Off,
Maybe,
On,
}
pub struct Lexer<'input> {
reader: &'input mut BufReader<File>,
lineno: u32,
first_column: usize,
current_column: usize,
peekChar: Option<char>,
scaneol: ScanEOL,
floatenable: bool,
}
impl<'input> Lexer<'input> {
pub fn new(reader: &'input mut BufReader<File>) -> Self {
Lexer { reader: reader, lineno: 1, first_column: 0,
current_column: 0, peekChar: None, scaneol: ScanEOL::Off,
floatenable: true }
}
fn PeekChar(&mut self) -> io::Result<Option<char>> {
if self.peekChar.is_none() {
let mut buffer: [u8; 1] = [0; 1];
let status = self.reader.read(&mut buffer)?;
if status > 0 {
self.peekChar = Some(buffer[0] as char);
}
}
Ok(self.peekChar)
}
fn ReadChar(&mut self) -> io::Result<Option<char>> {
if self.peekChar.is_none() {self.PeekChar()?;}
let result = self.peekChar;
self.peekChar = None;
Ok(result)
}
}
#[derive(Debug, PartialEq, Copy, Clone, Default)]
pub struct FileLocation {
lineno: u32,
column: usize,
}
impl FileLocation {
pub fn new(l: u32, c: usize) -> Self {
Self {lineno: l, column: c }
}
}
impl fmt::Display for FileLocation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Line:{}/Col:{}", self.lineno,self.column)
}
}
include!(concat!(env!("OUT_DIR"), "/keywords.rs"));
impl<'input> Iterator for Lexer<'input> {
type Item = Spanned<Tok, FileLocation, LexicalError>;
fn next(&mut self) -> Option<Self::Item> {
fn IsDigit(ch: char) -> bool {
match ch {
'0'..='9' => true,
_ => false,
}
}
fn IsAlpha(ch: char) -> bool {
match ch {
'a'..='z' => true,
'A'..='Z' => true,
_ => false,
}
}
let mut word: String = String::new();
let mut ch: char;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {return None;}
ch = nextChar.unwrap();
},
};
if self.scaneol == ScanEOL::On {
while ch != '\n' {
word.push(ch);
self.current_column += 1;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
}
self.peekChar = Some(ch);
let first = FileLocation::new(self.lineno,self.first_column);
let last = FileLocation::new(self.lineno,self.current_column);
self.first_column = self.current_column + 1;
self.scaneol = ScanEOL::Off;
return Some(Ok((first,Tok::STRINGTOEOL(word.clone()),last)));
} else {
while ch == ' ' || ch == '\t' {
self.current_column += 1;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
}
if ch == '\n' {
let first = FileLocation::new(self.lineno,self.first_column);
let last = FileLocation::new(self.lineno,self.current_column + 1);
self.first_column = 0;
self.current_column = 0;
self.lineno += 1;
return Some(Ok((first,Tok::EOL,last)));
}
if ch == '#' {
while ch != '\n' {
self.current_column += 1;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
}
let first = FileLocation::new(self.lineno, self.first_column);
let last = FileLocation::new(self.lineno,self.current_column + 1);
self.first_column = 0;
self.current_column = 0;
self.lineno += 1;
return Some(Ok((first,Tok::EOL,last)));
}
let mut peekch: char;
match self.PeekChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
peekch = '\n';
} else {
peekch = nextChar.unwrap();
}
},
};
if IsDigit(ch) ||
((ch == '+' || ch == '-') &&
IsDigit(peekch)) {
word.push(ch);
self.current_column += 1;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
while IsDigit(ch) {
word.push(ch);
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
self.current_column += 1;
}
if self.floatenable && ch == '.' {
word.push(ch);
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
self.current_column += 1;
while IsDigit(ch) {
word.push(ch);
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
self.current_column += 1;
}
self.peekChar = Some(ch);
let f: f64 = f64::from_str(&word).unwrap();
let result = Some(Ok((FileLocation::new(self.lineno,self.first_column),
Tok::FLOAT(f),
FileLocation::new(self.lineno,self.current_column+1))));
self.first_column = self.current_column+1;
return result;
}
self.peekChar = Some(ch);
let ui: u32 = u32::from_str(&word).unwrap();
let result = Some(Ok((FileLocation::new(self.lineno,self.first_column),
Tok::UINTEGER(ui),
FileLocation::new(self.lineno,self.current_column+1))));
self.first_column = self.current_column+1;
if self.scaneol == ScanEOL::Maybe {self.scaneol = ScanEOL::On;}
return result;
} else if IsAlpha(ch) {
while IsAlpha(ch) || ch == '$' {
word.push(ch.to_ascii_uppercase());
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
self.current_column += 1;
}
self.peekChar = Some(ch);
let firstColumn = FileLocation::new(self.lineno,self.first_column);
let lastColumn = FileLocation::new(self.lineno,self.current_column + 1);
self.first_column = self.current_column + 1;
let token = KEYWORDS.get(&word).cloned();
if token.is_none() {
return Some(Err(LexicalError::UnknownKeyword(word)));
} else {
let tok = token.unwrap();
match tok {
Tok::TITLE => {self.scaneol = ScanEOL::Maybe;},
Tok::VERSION => {self.floatenable = false;},
_ => {
self.scaneol = ScanEOL::Off;
self.floatenable = true;
},
};
return Some(Ok((firstColumn,tok,lastColumn)));
}
} else if ch == '"' {
let mut endOfString: bool = false;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
self.current_column += 1;
while !endOfString && ch != '\n' {
if ch == '\\' {
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
self.current_column += 1;
word.push(ch);
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
} else if ch == '"' {
match self.PeekChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
peekch = '\n';
} else {
peekch = nextChar.unwrap();
}
},
};
if peekch == '"' {
ch = peekch;
self.peekChar = None;
self.current_column += 1;
word.push(ch);
self.current_column += 1;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
} else {
endOfString = true;
}
} else if ch != '\n' {
word.push(ch);
self.current_column += 1;
match self.ReadChar() {
Err(message) => {return Some(Err(LexicalError::IOError(message.to_string())));},
Ok(nextChar) => {
if nextChar.is_none() {
ch = '\n';
} else {
ch = nextChar.unwrap();
}
},
};
} else {
return Some(Err(LexicalError::UnTerminatedString));
}
}
self.current_column += 1;
let firstCol = FileLocation::new(self.lineno,self.first_column);
let lastCol = FileLocation::new(self.lineno,self.current_column + 1);
self.first_column = self.current_column + 1;
return Some(Ok((firstCol,Tok::STRING(word.clone()),lastCol)));
} else if ch == '.' {
self.current_column += 1;
let firstCol = FileLocation::new(self.lineno,self.first_column);
let lastCol = FileLocation::new(self.lineno,self.current_column);
self.first_column = self.current_column+1;
return Some(Ok((firstCol,Tok::DOT,lastCol)));
} else {
return Some(Err(LexicalError::UnknownCharacter(ch)));
}
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum LayoutError {
ParseError(String),
FileError(String),
IOError(String),
}
impl fmt::Display for LayoutError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
LayoutError::ParseError(message) => write!(f, "Parse Error: {}", message),
LayoutError::FileError(message) => write!(f, "File error: {}", message),
LayoutError::IOError(message) => write!(f, "IO Error: {}", message),
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct Layer {
visible: bool,
frozen: bool,
on_map: bool,
color_rgb: u32,
module: u32,
dont_use_color: bool,
color_flags: u32,
button_off: bool,
name: String,
inherit: bool,
scale_index: u32,
min_track_radius: f64,
max_track_grade: f64,
tie_length: f64,
tie_width: f64,
tie_spacing: f64,
}
impl fmt::Display for Layer {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Layer {}>", self.name)
}
}
impl Layer {
pub fn new(visible: bool,frozen: bool,on_map: bool,color_rgb: u32,
module: u32,dont_use_color: bool,color_flags: u32,
button_off: bool,name: String,inherit: bool,scale_index: u32,
min_track_radius: f64,max_track_grade: f64,tie_length: f64,
tie_width: f64,tie_spacing: f64) -> Self {
Self {visible: visible,frozen: frozen,on_map: on_map,color_rgb:
color_rgb,module: module,dont_use_color: dont_use_color,
color_flags: color_flags,button_off: button_off,name: name,
inherit: inherit,scale_index: scale_index,
min_track_radius: min_track_radius,
max_track_grade: max_track_grade,tie_length: tie_length,
tie_width: tie_width,tie_spacing: tie_spacing}
}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn IsFrozenP(&self) -> bool {self.frozen}
pub fn IsOnMapP(&self) -> bool {self.on_map}
pub fn Color(&self) -> u32 {self.color_rgb}
pub fn Module(&self) -> u32 {self.module}
pub fn DontUseColotP(&self) -> bool {self.dont_use_color}
pub fn ColorFlags(&self) -> u32 {self.color_flags}
pub fn IsButtonOffP(&self) -> bool {self.button_off}
pub fn Name(&self) -> String {self.name.clone()}
pub fn InheritP(&self) -> bool {self.inherit}
pub fn ScaleIndex(&self) -> u32 {self.scale_index}
pub fn MinimumTrackRadius(&self) -> f64 {self.min_track_radius}
pub fn MaximumTrackGrade(&self) -> f64 {self.max_track_grade}
pub fn TieLength(&self) -> f64 {self.tie_length}
pub fn TieWidth(&self) -> f64 {self.tie_width}
pub fn TieSPacing(&self) -> f64 {self.tie_spacing}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Structure {
layer: u32,
lineType: u32,
scale: Scale,
visible: bool,
origx: f64,
origy: f64,
elev: u32,
angle: f64,
textfields: String,
adjopt: Option<(f64, f64)>,
pieropt: Option<(f64, String)>,
structbody: StructureBody,
}
impl fmt::Display for Structure {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut tabs = self.textfields.split('\t');
let manu = tabs.next().unwrap_or("");
let name = tabs.next().unwrap_or("");
let partno = tabs.next().unwrap_or("");
write!(f, "<#Structure ({},{},{})>", manu,name,partno)
}
}
impl Structure {
pub fn new(layer: u32, lineType: u32, scale: Scale, visible: bool,
origx: f64, origy: f64, elev: u32, angle: f64,
textfields: String, adjopt: Option<(f64, f64)>,
pieropt: Option<(f64, String)>, structbody: StructureBody)
-> Self {
Self { layer: layer, lineType: lineType, scale: scale,
visible: visible, origx: origx, origy: origy, elev: elev,
angle: angle, textfields: textfields, adjopt: adjopt,
pieropt: pieropt, structbody: structbody }
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn LineType(&self) -> u32 {self.lineType}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn XOrigin(&self) -> f64 {self.origx}
pub fn YOrigin(&self) -> f64 {self.origy}
pub fn Elevation(&self) -> u32 {self.elev}
pub fn Angle(&self) -> f64 {self.angle}
pub fn TextFields(&self) -> String {self.textfields.clone()}
pub fn AdjustableOptions(&self) -> Option<(f64, f64)> {self.adjopt}
pub fn PeirOptions(&self) -> Option<(f64, String)> {self.pieropt.clone()}
pub fn StructureBody(&self) -> StructureBody {self.structbody.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Drawing {
layer: u32,
lineType: u32,
start_x: f64,
start_y: f64,
start: u32,
angle: f64,
segments: StructureBody,
}
impl fmt::Display for Drawing {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Drawing {},{},{} {} segments>",
self.start_x,self.start_y,self.angle,
self.segments.len())
}
}
impl Drawing {
pub fn new(layer: u32, lineType: u32, start_x: f64, start_y: f64,
start: u32, angle: f64, segments: StructureBody) -> Self {
Self {layer: layer, lineType: lineType, start_x: start_x,
start_y: start_y, start: start, angle: angle, segments: segments}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn LineType(&self) -> u32 {self.lineType}
pub fn StartX(&self) -> f64 {self.start_x}
pub fn StartY(&self) -> f64 {self.start_y}
pub fn Start(&self) -> u32 {self.start}
pub fn Angle(&self) -> f64 {self.angle}
pub fn Segments(&self) -> StructureBody {self.segments.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct BZRLine {
layer: u32,
line_width: u32,
scale: Scale,
visible: bool,
x1: f64,
y1: f64,
x2: f64,
y2: f64,
x3: f64,
y3: f64,
x4: f64,
y4: f64,
desc_x: f64,
desc_y: f64,
body: BZRLineBody,
}
impl fmt::Display for BZRLine {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#BZRLine {} {} {} {} {} {} {} {}>", self.x1, self.y1,
self.x2,self.y2,self.x3,self.y3,self.x4,self.y4)
}
}
impl BZRLine {
pub fn new(layer: u32, line_width: u32, scale: Scale, visible: bool,
X1: f64, Y1: f64, X2: f64, Y2: f64, X3: f64, Y3: f64,
X4: f64, Y4: f64, desc_X: f64, desc_Y: f64, body: BZRLineBody)
-> Self {
Self {layer: layer, line_width: line_width, scale: scale,
visible: visible, x1: X1, y1: Y1, x2: X2, y2: Y2, x3: X3, y3: Y3,
x4: X4, y4: Y4, desc_x: desc_X, desc_y: desc_Y, body: body}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn LineWidth(&self) -> u32 {self.line_width}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn X1(&self) -> f64 {self.x1}
pub fn Y1(&self) -> f64 {self.y1}
pub fn X2(&self) -> f64 {self.x2}
pub fn Y2(&self) -> f64 {self.y2}
pub fn X3(&self) -> f64 {self.x3}
pub fn Y3(&self) -> f64 {self.y3}
pub fn X4(&self) -> f64 {self.x4}
pub fn Y4(&self) -> f64 {self.y4}
pub fn DescX(&self) -> f64 {self.desc_x}
pub fn DescY(&self) -> f64 {self.desc_y}
pub fn Body(&self) -> BZRLineBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Cornu {
layer: u32,
width: u32,
scale: Scale,
visible: bool,
pos1x: f64,
pos1y: f64,
angle1: f64,
radius1: f64,
center1x: f64,
center1y: f64,
pos2x: f64,
pos2y: f64,
angle2: f64,
radius2: f64,
center2x: f64,
center2y: f64,
body: CornuBody,
}
impl fmt::Display for Cornu {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Cornu {},{},{},{},{},{} {},{},{},{},{},{}>",
self.pos1x,self.pos1y,self.angle1,self.radius1,self.center1x,self.center1y,
self.pos2x,self.pos2y,self.angle2,self.radius2,self.center2x,self.center2y)
}
}
impl Cornu {
pub fn new(layer: u32, width: u32, scale: Scale, visible: bool, pos1x: f64,
pos1y: f64, angle1: f64, radius1: f64, center1x: f64,
center1y: f64, pos2x: f64, pos2y: f64, angle2: f64,
radius2: f64, center2x: f64, center2y: f64, body: CornuBody) -> Self {
Self {layer: layer, width: width, scale: scale, visible: visible,
pos1x: pos1x, pos1y: pos1y, angle1: angle1, radius1: radius1,
center1x: center1x, center1y: center1y, pos2x: pos2x,
pos2y: pos2y, angle2: angle2, radius2: radius2,
center2x: center2x, center2y: center2y, body: body}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Width(&self) -> u32 {self.width}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn Pos1x(&self) -> f64 {self.pos1x}
pub fn Pos1y(&self) -> f64 {self.pos1y}
pub fn Angle1(&self) -> f64 {self.angle1}
pub fn Radius1(&self) -> f64 {self.radius1}
pub fn Center1x(&self) -> f64 {self.center1x}
pub fn Center1y(&self) -> f64 {self.center1y}
pub fn Pos2x(&self) -> f64 {self.pos2x}
pub fn Pos2y(&self) -> f64 {self.pos2y}
pub fn Angle2(&self) -> f64 {self.angle2}
pub fn Radius2(&self) -> f64 {self.radius2}
pub fn Center2x(&self) -> f64 {self.center2x}
pub fn Center2y(&self) -> f64 {self.center2y}
pub fn Body(&self) -> CornuBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Curve {
layer: u32,
line_width: u32,
scale: Scale,
flags: u32,
center_x: f64,
center_y: f64,
radius: f64,
helix_turns: u32,
desc_x: f64,
desc_y: f64,
trackbody: TrackBody,
}
impl fmt::Display for Curve {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Curve {},{},{} {} turns {},{}>",self.center_x,
self.center_y,self.radius,self.helix_turns,self.desc_x,
self.desc_y)
}
}
impl Curve {
pub fn new(layer: u32, line_width: u32, scale: Scale, flags: u32,
center_X: f64, center_Y: f64, radius: f64, helix_turns: u32,
desc_X: f64, desc_Y: f64, trackbody: TrackBody) -> Self {
Self {layer: layer, line_width: line_width, scale: scale,
flags: flags, center_x: center_X, center_y: center_Y,
radius: radius, helix_turns: helix_turns, desc_x: desc_X,
desc_y: desc_Y, trackbody: trackbody}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn LineWidth(&self) -> u32 {self.line_width}
pub fn Scale(&self) -> Scale {self.scale}
pub fn Flags(&self) -> u32 {self.flags}
pub fn CenterX(&self) -> f64 {self.center_x}
pub fn CenterY(&self) -> f64 {self.center_y}
pub fn Radius(&self) -> f64 {self.radius}
pub fn HelixTurns(&self) -> u32 {self.helix_turns}
pub fn DescX(&self) -> f64 {self.desc_x}
pub fn DescY(&self) -> f64 {self.desc_y}
pub fn Trackbody(&self) -> TrackBody {self.trackbody.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Bezier {
layer: u32,
width: u32,
color: u32,
scale: Scale,
visible: bool,
x1: f64,
y1: f64,
x2: f64,
y2: f64,
x3: f64,
y3: f64,
x4: f64,
y4: f64,
desc_x: f64,
desc_y: f64,
body: BezierBody,
}
impl fmt::Display for Bezier {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Bezier {} {} {} {} {} {} {} {}>", self.x1, self.y1,
self.x2,self.y2,self.x3,self.y3,self.x4,self.y4)
}
}
impl Bezier {
pub fn new(layer: u32, width: u32, color: u32, scale: Scale, visible: bool,
X1: f64, Y1: f64, X2: f64, Y2: f64, X3: f64, Y3: f64,
X4: f64, Y4: f64, desc_X: f64, desc_Y: f64, body: BezierBody) -> Self {
Self {layer: layer, width: width, color: color, scale: scale,
visible: visible, x1: X1, y1: Y1, x2: X2, y2: Y2, x3: X3,
y3: Y3, x4: X4, y4: Y4, desc_x: desc_X, desc_y: desc_Y,
body: body }
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Width(&self) -> u32 {self.width}
pub fn Color(&self) -> u32 {self.color}
pub fn Scale(&self) -> Scale {self.scale}
pub fn Visible(&self) -> bool {self.visible}
pub fn X1(&self) -> f64 {self.x1}
pub fn Y1(&self) -> f64 {self.y1}
pub fn X2(&self) -> f64 {self.x2}
pub fn Y2(&self) -> f64 {self.y2}
pub fn X3(&self) -> f64 {self.x3}
pub fn Y3(&self) -> f64 {self.y3}
pub fn X4(&self) -> f64 {self.x4}
pub fn Y4(&self) -> f64 {self.y4}
pub fn DescX(&self) -> f64 {self.desc_x}
pub fn DescY(&self) -> f64 {self.desc_y}
pub fn Body(&self) -> BezierBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Straight {
layer: u32,
line_width: u32,
scale: Scale,
flags: u32,
desc_x: f64,
desc_y: f64,
body: TrackBody,
}
impl fmt::Display for Straight {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Straight {},{}>",self.desc_x,self.desc_y)
}
}
impl Straight {
pub fn new(layer: u32, line_width: u32, scale: Scale, flags: u32,
Desc_x: f64, Desc_y: f64, body: TrackBody) -> Self {
Self { layer: layer, line_width: line_width, scale: scale,
flags: flags, desc_x: Desc_x, desc_y: Desc_y, body: body }
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn LineWidth(&self) -> u32 {self.line_width}
pub fn Scale(&self) -> Scale {self.scale}
pub fn Flags(&self) -> u32 {self.flags}
pub fn DescX(&self) -> f64 {self.desc_x}
pub fn DescY(&self) -> f64 {self.desc_y}
pub fn Body(&self) -> TrackBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Turnout {
layer: u32,
options: u32,
postion: u32,
scale: Scale,
flags: u32,
origx: f64,
origy: f64,
elev: u32,
angle: f64,
tablist: String,
adjopt: Option<(f64, f64)>,
pieropt: Option<(f64, String)>,
body: TurnoutBody,
}
impl fmt::Display for Turnout {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Turnout {}>",self.tablist)
}
}
impl Turnout {
pub fn new(layer: u32, options: u32, postion: u32, scale: Scale,
flags: u32, origx: f64, origy: f64, elev: u32, angle: f64,
tablist: String, adjopt: Option<(f64, f64)>,
pieropt: Option<(f64, String)>, body: TurnoutBody, ) -> Self {
Self {layer: layer, options: options, postion: postion, scale: scale,
flags: flags, origx: origx, origy: origy, elev: elev,
angle: angle, tablist: tablist, adjopt: adjopt,
pieropt: pieropt, body: body}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Options(&self) -> u32 {self.options}
pub fn Postion(&self) -> u32 {self.postion}
pub fn Scale(&self) -> Scale {self.scale}
pub fn Flags(&self) -> u32 {self.flags}
pub fn OrigX(&self) -> f64 {self.origx}
pub fn OrigY(&self) -> f64 {self.origy}
pub fn Elev(&self) -> u32 {self.elev}
pub fn Angle(&self) -> f64 {self.angle}
pub fn Tablist(&self) -> String {self.tablist.clone()}
pub fn AdjOpt(&self) -> Option<(f64, f64)> {self.adjopt}
pub fn PierOpt(&self) -> Option<(f64, String)> {self.pieropt.clone()}
pub fn Body(&self) -> TurnoutBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Turntable {
layer:u32,
scale: Scale,
visible: bool,
x: f64,
y: f64,
radius: f64,
current_ep: Option<u32>,
body: TrackBody,
}
impl fmt::Display for Turntable {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Turntable {},{},{}>",self.x,self.y,self.radius)
}
}
impl Turntable {
pub fn new(layer:u32, scale: Scale, visible: bool, x: f64, y: f64,
radius: f64, current_ep: Option<u32>, body: TrackBody) -> Self {
Self {layer: layer, scale: scale, visible: visible, x: x, y: y,
radius: radius, current_ep: current_ep, body: body }
}
pub fn Layer(&self) ->u32 {self.layer}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn X(&self) -> f64 {self.x}
pub fn Y(&self) -> f64 {self.y}
pub fn Radius(&self) -> f64 {self.radius}
pub fn CurrentEp(&self) -> Option<u32> {self.current_ep}
pub fn Body(&self) -> TrackBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Joint {
layer: u32,
width: u32,
scale: Scale,
flags: u32,
l0: f64,
l1: f64,
r: f64,
flip: u32,
negate: u32,
s_curve: u32,
x: f64,
y: f64,
angle: f64,
desc_x: f64,
desc_y: f64,
body: TrackBody,
}
impl fmt::Display for Joint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Joint {},{}>",self.x,self.y)
}
}
impl Joint {
pub fn new(layer: u32, width: u32, scale: Scale, flags: u32, l0: f64,
l1: f64, R: f64, flip: u32, negate: u32, S_curve: u32,
x: f64, y: f64, angle: f64, desc_x: f64, desc_y: f64,
body: TrackBody) -> Self {
Self {layer: layer, width: width, scale: scale, flags: flags,
l0: l0, l1: l1, r: R, flip: flip, negate: negate,
s_curve: S_curve, x: x, y: y, angle: angle, desc_x: desc_x,
desc_y: desc_y, body: body}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Width(&self) -> u32 {self.width}
pub fn Scale(&self) -> Scale {self.scale}
pub fn Flags(&self) -> u32 {self.flags}
pub fn L0(&self) -> f64 {self.l0}
pub fn L1(&self) -> f64 {self.l1}
pub fn R(&self) -> f64 {self.r}
pub fn Flip(&self) -> u32 {self.flip}
pub fn Negate(&self) -> u32 {self.negate}
pub fn SCurve(&self) -> u32 {self.s_curve}
pub fn X(&self) -> f64 {self.x}
pub fn Y(&self) -> f64 {self.y}
pub fn Angle(&self) -> f64 {self.angle}
pub fn DescX(&self) -> f64 {self.desc_x}
pub fn DescY(&self) -> f64 {self.desc_y}
pub fn Body(&self) -> TrackBody {self.body.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Car {
scale: Scale,
title: String,
options: u32,
typeofcar: u32,
length: f64,
width: f64,
truck_center_offset: u32,
truck_center: f64,
coupled_length: f64,
color: u32,
puchaseprice: f64,
currentprice: f64,
condition: u32,
purchdate: u32,
servdate: u32,
notes: String,
onlayout: Option<CarAux>,
}
impl fmt::Display for Car {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Car {}>", self.title)
}
}
impl Car {
pub fn new(scale: Scale, title: String, options: u32, typeofcar: u32,
length: f64, width: f64, truck_center_offset: u32,
truck_center: f64, coupled_length: f64, color: u32,
puchaseprice: f64, currentprice: f64, condition: u32,
purchdate: u32, servdate: u32, notes: String,
onlayout: Option<CarAux>) -> Self {
Self {scale: scale, title: title, options: options,
typeofcar: typeofcar, length: length, width: width,
truck_center_offset: truck_center_offset,
truck_center: truck_center, coupled_length: coupled_length,
color: color, puchaseprice: puchaseprice,
currentprice: currentprice, condition: condition,
purchdate: purchdate, servdate: servdate, notes: notes,
onlayout: onlayout}
}
pub fn Scale(&self) -> Scale {self.scale}
pub fn Title(&self) -> String {self.title.clone()}
pub fn Options(&self) -> u32 {self.options}
pub fn TypeOfCar(&self) -> u32 {self.typeofcar}
pub fn Length(&self) -> f64 {self.length}
pub fn Width(&self) -> f64 {self.width}
pub fn TruckCenterOffset(&self) -> u32 {self.truck_center_offset}
pub fn TruckCenter(&self) -> f64 {self.truck_center}
pub fn CoupledLength(&self) -> f64 {self.coupled_length}
pub fn Color(&self) -> u32 {self.color}
pub fn PuchasePrice(&self) -> f64 {self.puchaseprice}
pub fn CurrentPrice(&self) -> f64 {self.currentprice}
pub fn Condition(&self) -> u32 {self.condition}
pub fn PurchDate(&self) -> u32 {self.purchdate}
pub fn ServDate(&self) -> u32 {self.servdate}
pub fn Notes(&self) -> String {self.notes.clone()}
pub fn OnLayout(&self) -> Option<CarAux> {self.onlayout.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Note {
layer: u32,
start_x: f64,
start_y: f64,
length: u32,
typeofnote: u32,
text1: String,
text2: Option<String>,
}
impl fmt::Display for Note {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Note {}>", self.text1)
}
}
impl Note {
pub fn new (layer: u32, start_x: f64, start_y: f64, length: u32,
typeofnote: u32, text1: String, text2: Option<String>) -> Self {
Self {layer: layer, start_x: start_x, start_y: start_y,
length: length, typeofnote: typeofnote, text1: text1,
text2: text2 }
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn StartX(&self) -> f64 {self.start_x}
pub fn StartY(&self) -> f64 {self.start_y}
pub fn Length(&self) -> u32 {self.length}
pub fn TypeOfNote(&self) -> u32 {self.typeofnote}
pub fn Text1(&self) -> String {self.text1.clone()}
pub fn Text2(&self) -> Option<String> {self.text2.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TextItem {
layer: u32,
color: u32,
font_size: u32,
x: f64,
y: f64,
check_box: bool,
text: String,
rotation: u32,
}
impl fmt::Display for TextItem {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#TextItem {}>", self.text)
}
}
impl TextItem {
pub fn new(layer: u32, color: u32, font_size: u32, x: f64, y: f64, check_box: bool, text: String, rotation: u32) -> Self {
Self {layer: layer, color: color, font_size: font_size, x: x, y: y,
check_box: check_box, text: text, rotation: rotation }
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Color(&self) -> u32 {self.color}
pub fn FontSize(&self) -> u32 {self.font_size}
pub fn X(&self) -> f64 {self.x}
pub fn Y(&self) -> f64 {self.y}
pub fn HasCheckBoxP(&self) -> bool {self.check_box}
pub fn Text(&self) -> String {self.text.clone()}
pub fn Rotation(&self) -> u32 {self.rotation}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Block {
name: String,
script: String,
tracklist: IntegerList,
}
impl fmt::Display for Block {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Block {}>", self.name)
}
}
impl Block {
pub fn new(name: String, script: String, tracklist: IntegerList) -> Self {
Self{name: name, script: script, tracklist: tracklist, }
}
pub fn Name(&self) -> String {self.name.clone()}
pub fn Script(&self) -> String {self.script.clone()}
pub fn Tracklist(&self) -> IntegerList {self.tracklist.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct SwitchMotor {
turnout: u32,
name: String,
normal: String,
reverse: String,
pointsense: String,
}
impl fmt::Display for SwitchMotor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#SwitchMotor {}>", self.name)
}
}
impl SwitchMotor {
pub fn new(turnout: u32, name: String, normal: String, reverse: String,
pointsense: String) -> Self {
Self {turnout: turnout, name: name, normal: normal, reverse: reverse,
pointsense: pointsense,}
}
pub fn Turnout(&self) -> u32 {self.turnout}
pub fn Name(&self) -> String {self.name.clone()}
pub fn Normal(&self) -> String {self.normal.clone()}
pub fn Reverse(&self) -> String {self.reverse.clone()}
pub fn Pointsense(&self) -> String {self.pointsense.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Signal {
layer: u32,
scale: Scale,
visible: bool,
x: f64,
y: f64,
a: f64,
numheads: u32,
name: String,
aspectlist: AspectList,
}
impl fmt::Display for Signal {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Signal {}>",self.name)
}
}
impl Signal {
pub fn new(layer: u32, scale: Scale, visible: bool, X: f64, Y: f64, A: f64,
numheads: u32, name: String, aspectlist: AspectList) -> Self {
Self {layer: layer, scale: scale, visible: visible, x: X, y: Y, a: A,
numheads: numheads, name: name, aspectlist: aspectlist,}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn X(&self) -> f64 {self.x}
pub fn Y(&self) -> f64 {self.y}
pub fn A(&self) -> f64 {self.a}
pub fn Numheads(&self) -> u32 {self.numheads}
pub fn Name(&self) -> String {self.name.clone()}
pub fn Aspectlist(&self) -> AspectList {self.aspectlist.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Sensor {
layer: u32,
scale: Scale,
visible: bool,
x: f64,
y: f64,
name: String,
script: String,
}
impl fmt::Display for Sensor {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Sensor {}>", self.name)
}
}
impl Sensor {
pub fn new(layer: u32, scale: Scale, visible: bool, X: f64, Y: f64,
name: String, script: String) -> Self {
Self {layer: layer, scale: scale, visible: visible, x: X, y: Y,
name: name, script: script,}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn X(&self) -> f64 {self.x}
pub fn Y(&self) -> f64 {self.y}
pub fn Name(&self) -> String {self.name.clone()}
pub fn Script(&self) -> String {self.script.clone()}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Control {
layer: u32,
scale: Scale,
visible: bool,
start_x: f64,
start_y: f64,
name: String,
on_script: String,
off_script: String,
}
impl fmt::Display for Control {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Control {}>",self.name)
}
}
impl Control {
pub fn new(layer: u32, scale: Scale, visible: bool, start_x: f64,
start_y: f64, name: String, on_script: String,
off_script: String) -> Self {
Self {layer: layer, scale: scale, visible: visible, start_x: start_x,
start_y: start_y, name: name, on_script: on_script,
off_script: off_script}
}
pub fn Layer(&self) -> u32 {self.layer}
pub fn Scale(&self) -> Scale {self.scale}
pub fn IsVisibleP(&self) -> bool {self.visible}
pub fn StartX(&self) -> f64 {self.start_x}
pub fn StartY(&self) -> f64 {self.start_y}
pub fn Name(&self) -> String {self.name.clone()}
pub fn OnScript(&self) -> String {self.on_script.clone()}
pub fn OffScript(&self) -> String {self.off_script.clone()}
}
#[derive(Debug)]
pub struct Layout {
filename: String,
file_version: u32,
program_version: (u32,u32,u32),
title1: String,
title2: String,
mapscale: u32,
roomsize: (f64,f64),
scale: Scale,
layers: HashMap<u32,Layer>,
current_layer: u32,
structures: HashMap<u32,Structure>,
drawings: HashMap<u32,Drawing>,
bzrlines: HashMap<u32,BZRLine>,
cornus: HashMap<u32,Cornu>,
curves: HashMap<u32,Curve>,
beziers: HashMap<u32,Bezier>,
straights: HashMap<u32,Straight>,
turnouts: HashMap<u32,Turnout>,
turntables: HashMap<u32,Turntable>,
joints: HashMap<u32,Joint>,
cars: HashMap<u32,Car>,
notes: HashMap<u32,Note>,
textitems: HashMap<u32,TextItem>,
blocks: HashMap<u32,Block>,
switchmotors: HashMap<u32,SwitchMotor>,
signals: HashMap<u32,Signal>,
sensors: HashMap<u32,Sensor>,
controls: HashMap<u32,Control>,
}
impl fmt::Display for Layout {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#Layout {}>", self.title1)
}
}
impl Layout {
pub fn new(layoutfilename: String) -> Result<Self, LayoutError> {
let mut this = Self{filename: layoutfilename.clone(), file_version: 0,
program_version: (0,0,0),
title1: String::new(), title2: String::new(),
mapscale: 1, roomsize: (1.0,1.0),
scale: Scale::HO, layers: HashMap::new(),
current_layer: 0, structures: HashMap::new(),
drawings: HashMap::new(),
bzrlines: HashMap::new(),
cornus: HashMap::new(), curves: HashMap::new(),
beziers: HashMap::new(),
straights: HashMap::new(),
turnouts: HashMap::new(),
turntables: HashMap::new(),
joints: HashMap::new(), cars: HashMap::new(),
notes: HashMap::new(),
textitems: HashMap::new(), blocks: HashMap::new(),
switchmotors: HashMap::new(),
signals: HashMap::new(), sensors: HashMap::new(),
controls: HashMap::new(),
};
let file = match File::open(&layoutfilename) {
Ok(f) => f,
Err(message) => {
return Err(LayoutError::FileError(message.to_string()));
},
};
let mut reader = BufReader::new(file);
let lexer = Lexer::new(&mut reader);
let parser = xtrakcad::XtrakCadLayoutParser::new();
match parser.parse(&mut this,lexer) {
Ok(()) => (),
Err(message) => {
return Err(LayoutError::ParseError(message.to_string()));
},
};
Ok(this)
}
pub fn SetVersion(&mut self,fver: u32, major: u32, minor: u32,
release: u32) {
self.file_version = fver;
self.program_version = (major, minor, release);
}
pub fn SetTitle(&mut self,level: u32, text: String) {
match level {
1 => {self.title1 = text.trim().to_string();},
2 => {self.title2 = text.trim().to_string();},
_ => (),
};
}
pub fn SetMapscale(&mut self,mapscale: u32) {
self.mapscale = mapscale;
}
pub fn SetRoomsize(&mut self,width: f64, height: f64) {
self.roomsize = (width,height);
}
pub fn SetScale(&mut self,scale: Scale) {
self.scale = scale;
}
pub fn AddLayer(&mut self,lnum: u32,visible: u32,frozen: u32,on_map: u32,
color_rgb: u32,module: u32,dont_use_color: u32,
color_flags: u32,button_off: u32,name: String,inherit: u32,
scale_index: u32,min_track_radius: f64,
max_track_grade: f64,tie_length: f64,tie_width: f64,
tie_spacing:f64) {
self.layers.insert(lnum,Layer::new(visible != 0,frozen != 0,
on_map != 0, color_rgb,module,
dont_use_color != 0, color_flags,
button_off != 0,name,inherit!= 0,
scale_index,min_track_radius,
max_track_grade,tie_length,
tie_width,tie_spacing));
}
pub fn SetCurrentLayer(&mut self,lnum: u32) {
self.current_layer = lnum;
}
pub fn AddStructure(&mut self,index: u32, layer: u32, lineType: u32,
pad1: u32, pad2: u32, scale: Scale, visible: u32,
origx: f64, origy: f64, elev: u32, angle: f64,
textfields: String, adjopt: Option<(f64, f64)>,
pieropt: Option<(f64, String)>,
structbody: StructureBody) {
self.structures.insert(index, Structure::new(layer,lineType,scale,
visible!=0,origx,origy,
elev,angle,textfields,
adjopt,pieropt,
structbody));
}
pub fn AddDrawing(&mut self,index: u32, layer: u32, lineType: u32,
pad1: u32, pad2: u32, start_x: f64, start_y: f64,
start: u32, angle: f64, segments: StructureBody) {
self.drawings.insert(index,Drawing::new(layer,lineType,start_x,start_y,
start,angle,segments));
}
pub fn AddBZRLine(&mut self,index: u32, layer: u32, pad1: u32, pad2: u32,
line_width: u32, scale: Scale, visible: u32, X1: f64,
Y1: f64,X2: f64,Y2: f64,X3: f64,Y3: f64,X4: f64,Y4: f64,
pad3: u32,desc_X: f64,desc_Y: f64, body: BZRLineBody) {
self.bzrlines.insert(index,BZRLine::new(layer,line_width,scale,
visible!=0,X1,Y1,X2,Y2,X3,Y3,
X4,Y4,desc_X,desc_Y,body));
}
pub fn AddCornu(&mut self,index: u32,layer: u32,width: u32,pad1: u32,
pad2: u32,scale: Scale,visible: u32,pos1x: f64,pos1y: f64,
angle1: f64,radius1: f64,center1x: f64,center1y: f64,
pos2x: f64,pos2y: f64,angle2: f64,radius2: f64,
center2x: f64,center2y: f64,body: CornuBody) {
self.cornus.insert(index,Cornu::new(layer,width,scale,visible!=0,
pos1x,pos1y,angle1,radius1,
center1x,center1y,pos2x,pos2y,
angle2,radius2,center2x,center2y,
body));
}
pub fn AddCurve(&mut self,index: u32, layer: u32, line_width: u32,
pad1: u32, pad2: u32, scale: Scale, flags: u32,
center_X: f64, centerY: f64, pad3: u32, radius: f64,
helix_turns: u32, desc_X: f64, desc_Y: f64,
trackbody: TrackBody) {
self.curves.insert(index, Curve::new(layer, line_width, scale,
flags, center_X, centerY, radius,
helix_turns, desc_X, desc_Y,
trackbody));
}
pub fn AddBezier(&mut self,index: u32, layer: u32, width: u32, color: u32,
pad1: f64, scale: Scale, vis: u32, X1: f64, Y1: f64,
X2: f64, Y2: f64, X3: f64, Y3: f64, X4: f64, Y4: f64,
pad2: u32, desc_X: f64, desc_Y: f64, body: BezierBody) {
self.beziers.insert(index,Bezier::new(layer, width, color, scale,
vis!=0, X1, Y1, X2, Y2, X3, Y3,
X4, Y4, desc_X, desc_Y, body));
}
pub fn AddStraight(&mut self,index: u32, layer: u32, line_width: u32,
pad1: u32, pad2: u32, scale: Scale, flags: u32,
Desc_x: f64, Desc_y: f64, body: TrackBody) {
self.straights.insert(index,Straight::new(layer, line_width, scale,
flags, Desc_x, Desc_y,
body));
}
pub fn AddTurnout(&mut self,index: u32, layer: u32, options: u32,
postion: u32, pad1: u32, scale: Scale, flags: u32,
origx: f64, origy: f64, elev: u32, angle: f64,
tablist: String, adjopt: Option<(f64, f64)>,
pieropt: Option<(f64, String)>, body: TurnoutBody) {
self.turnouts.insert(index,Turnout::new(layer, options, postion,
scale, flags, origx,
origy, elev, angle, tablist,
adjopt, pieropt, body));
}
pub fn AddTurntable(&mut self,index: u32, layer:u32, pad1: u32, pad2: u32,
pad3: u32, scale: Scale, visible: u32, x: f64,
y: f64, pad4: u32, radius: f64,
current_ep: Option<u32>, body: TrackBody) {
self.turntables.insert(index,Turntable::new(layer, scale, visible!=0,
x, y, radius, current_ep,
body));
}
pub fn AddJoint(&mut self,index: u32, layer: u32, width: u32,
pad1: u32, pad2: u32, scale: Scale, flags: u32,
l0: f64, l1: f64, R: f64, flip: u32, negate: u32,
S_curve: u32, x: f64, y: f64, pad3: u32, angle: f64,
desc_x: f64, desc_y: f64, body: TrackBody) {
self.joints.insert(index,Joint::new(layer,width,scale,flags,l0,l1,R,
flip,negate,S_curve,x,y,angle,desc_x,desc_y,body));
}
pub fn AddCar(&mut self,inx: u32, scale: Scale, title: String,
options: u32, typeofcar: u32, length: f64, width: f64,
pad0: u32,truck_center_offset: u32, truck_center: f64,
coupled_length: f64, color: u32, puchaseprice: f64,
currentprice: f64, condition: u32, purchdate: u32,
servdate: u32, pad1: u32,pad2: u32,pad3: u32,pad4: u32,
pad5: u32, pad6: u32, notes: String,
onlayout: Option<CarAux>) {
self.cars.insert(inx,Car::new(scale, title.clone(), options,
typeofcar, length, width,
truck_center_offset, truck_center,
coupled_length, color, puchaseprice,
currentprice, condition, purchdate,
servdate, notes.clone(),
onlayout.clone()));
}
pub fn AddNote(&mut self,index: u32, layer: u32, pad1: u32, pad2: u32,
start_x: f64, start_y: f64, length: u32, typeofnote: u32,
text1: String, text2: Option<String>) {
self.notes.insert(index,Note::new(layer, start_x, start_y, length,
typeofnote, text1.clone(),
text2.clone()));
}
pub fn AddText(&mut self,index: u32, layer: u32, color: u32,
font_size: u32, pad1: u32, x: f64, y: f64, check_box: u32,
text: String, rotation: u32) {
self.textitems.insert(index,TextItem::new(layer, color, font_size,
x, y, check_box!=0,
text.clone(), rotation));
}
pub fn AddBlock(&mut self,index: u32, name: String, script: String, tracklist: IntegerList) {
self.blocks.insert(index,Block::new(name.clone(), script.clone(),
tracklist.clone()));
}
pub fn AddSwitchMotor(&mut self,index: u32,turnout: u32,name: String,
normal: String ,reverse: String,pointsense: String) {
self.switchmotors.insert(index,SwitchMotor::new(turnout,name.clone(),
normal.clone(),
reverse.clone(),
pointsense.clone()));
}
pub fn AddSignal(&mut self,index: u32,layer: u32, scale: Scale,
visible: u32, X: f64, Y: f64, A: f64, numheads: u32,
name: String, aspectlist: AspectList) {
self.signals.insert(index,Signal::new(layer,scale,visible!=0,X,Y,A,
numheads,name.clone(),
aspectlist.clone()));
}
pub fn AddSensor(&mut self,index: u32,layer: u32,scale: Scale,visible: u32,
X: f64,Y: f64,name: String,script: String) {
self.sensors.insert(index,Sensor::new(layer,scale,visible!=0,X,Y,
name.clone(),script.clone()));
}
pub fn AddControl(&mut self,index: u32,layer: u32,scale: Scale,
visible: u32, start_x: f64, start_y: f64,
name: String, on_script: String, off_script: String) {
self.controls.insert(index,Control::new(layer,scale,visible!=0,start_x,
start_y,name.clone(),
on_script.clone(),
off_script.clone()));
}
pub fn Filename(&self) -> String {self.filename.clone()}
pub fn FileVersion(&self) -> u32 {self.file_version}
pub fn ProgramVersion(&self) -> (u32,u32,u32) {self.program_version}
pub fn Title(&self) -> String {self.title1.clone()}
pub fn SubTitle(&self) -> String {self.title2.clone()}
pub fn MapScale(&self) -> u32 {self.mapscale}
pub fn RoomSize(&self) -> (f64,f64) {self.roomsize}
pub fn Scale(&self) -> Scale {self.scale}
pub fn LayerIndexes(&self) -> Vec<&u32> {
self.layers.keys().collect()
}
pub fn Layer(&self, i: u32) -> Option<&Layer> {self.layers.get(&i)}
pub fn LayerIter(&self) -> impl Iterator<Item = (&u32, &Layer)> {
self.layers.iter()
}
pub fn CurrentLayerNumber(&self) -> u32 {self.current_layer}
pub fn StructureIndexes(&self) -> Vec<&u32> {
self.structures.keys().collect()
}
pub fn Structure(&self, i: u32) -> Option<&Structure> {self.structures.get(&i)}
pub fn StructureIter(&self) -> impl Iterator<Item = (&u32, &Structure)> {
self.structures.iter()
}
pub fn DrawingIndexes(&self) -> Vec<&u32> {
self.drawings.keys().collect()
}
pub fn Drawing(&self, i: u32) -> Option<&Drawing> {self.drawings.get(&i)}
pub fn DrawingIter(&self) -> impl Iterator<Item = (&u32, &Drawing)> {
self.drawings.iter()
}
pub fn BZRLineIndexes(&self) -> Vec<&u32> {
self.bzrlines.keys().collect()
}
pub fn BZRLine(&self, i: u32) -> Option<&BZRLine> {self.bzrlines.get(&i)}
pub fn BZRLineIter(&self) -> impl Iterator<Item = (&u32, &BZRLine)> {
self.bzrlines.iter()
}
pub fn CornuIndexes(&self) -> Vec<&u32> {
self.cornus.keys().collect()
}
pub fn Cornu(&self, i: u32) -> Option<&Cornu> {self.cornus.get(&i)}
pub fn CornuIter(&self) -> impl Iterator<Item = (&u32, &Cornu)> {
self.cornus.iter()
}
pub fn CurveIndexes(&self) -> Vec<&u32> {
self.curves.keys().collect()
}
pub fn Curve(&self, i: u32) -> Option<&Curve> {self.curves.get(&i)}
pub fn CurveIter(&self) -> impl Iterator<Item = (&u32, &Curve)> {
self.curves.iter()
}
pub fn BezierIndexes(&self) -> Vec<&u32> {
self.beziers.keys().collect()
}
pub fn Bezier(&self, i: u32) -> Option<&Bezier> {self.beziers.get(&i)}
pub fn BezierIter(&self) -> impl Iterator<Item = (&u32, &Bezier)> {
self.beziers.iter()
}
pub fn StraightIndexes(&self) -> Vec<&u32> {
self.straights.keys().collect()
}
pub fn Straight(&self, i: u32) -> Option<&Straight> {self.straights.get(&i)}
pub fn StraightIter(&self) -> impl Iterator<Item = (&u32, &Straight)> {
self.straights.iter()
}
pub fn TurnoutIndexes(&self) -> Vec<&u32> {
self.turnouts.keys().collect()
}
pub fn Turnout(&self, i: u32) -> Option<&Turnout> {self.turnouts.get(&i)}
pub fn TurnoutIter(&self) -> impl Iterator<Item = (&u32, &Turnout)> {
self.turnouts.iter()
}
pub fn TurntableIndexes(&self) -> Vec<&u32> {
self.turntables.keys().collect()
}
pub fn Turntable(&self, i: u32) -> Option<&Turntable> {self.turntables.get(&i)}
pub fn TurntableIter(&self) -> impl Iterator<Item = (&u32, &Turntable)> {
self.turntables.iter()
}
pub fn JointIndexes(&self) -> Vec<&u32> {
self.joints.keys().collect()
}
pub fn Joint(&self, i: u32) -> Option<&Joint> {self.joints.get(&i)}
pub fn JointIter(&self) -> impl Iterator<Item = (&u32, &Joint)> {
self.joints.iter()
}
pub fn CarIndexes(&self) -> Vec<&u32> {
self.cars.keys().collect()
}
pub fn Car(&self, i: u32) -> Option<&Car> {self.cars.get(&i)}
pub fn CarIter(&self) -> impl Iterator<Item = (&u32, &Car)> {
self.cars.iter()
}
pub fn NoteIndexes(&self) -> Vec<&u32> {
self.notes.keys().collect()
}
pub fn Note(&self, i: u32) -> Option<&Note> {self.notes.get(&i)}
pub fn NoteIter(&self) -> impl Iterator<Item = (&u32, &Note)> {
self.notes.iter()
}
pub fn TextItemIndexes(&self) -> Vec<&u32> {
self.textitems.keys().collect()
}
pub fn TextItem(&self, i: u32) -> Option<&TextItem> {self.textitems.get(&i)}
pub fn TextItemIter(&self) -> impl Iterator<Item = (&u32, &TextItem)> {
self.textitems.iter()
}
pub fn BlockIndexes(&self) -> Vec<&u32> {
self.blocks.keys().collect()
}
pub fn Block(&self, i: u32) -> Option<&Block> {self.blocks.get(&i)}
pub fn BlockIter(&self) -> impl Iterator<Item = (&u32, &Block)> {
self.blocks.iter()
}
pub fn SwitchMotorIndexes(&self) -> Vec<&u32> {
self.switchmotors.keys().collect()
}
pub fn SwitchMotor(&self, i: u32) -> Option<&SwitchMotor> {self.switchmotors.get(&i)}
pub fn SwitchMotorIter(&self) -> impl Iterator<Item = (&u32, &SwitchMotor)> {
self.switchmotors.iter()
}
pub fn SignalIndexes(&self) -> Vec<&u32> {
self.signals.keys().collect()
}
pub fn Signal(&self, i: u32) -> Option<&Signal> {self.signals.get(&i)}
pub fn SignalIter(&self) -> impl Iterator<Item = (&u32, &Signal)> {
self.signals.iter()
}
pub fn SensorIndexes(&self) -> Vec<&u32> {
self.sensors.keys().collect()
}
pub fn Sensor(&self, i: u32) -> Option<&Sensor> {self.sensors.get(&i)}
pub fn SensorIter(&self) -> impl Iterator<Item = (&u32, &Sensor)> {
self.sensors.iter()
}
pub fn ControlIndexes(&self) -> Vec<&u32> {
self.controls.keys().collect()
}
pub fn Control(&self, i: u32) -> Option<&Control> {self.controls.get(&i)}
pub fn ControlIter(&self) -> impl Iterator<Item = (&u32, &Control)> {
self.controls.iter()
}
}
#[derive(Debug, PartialEq, Copy, Clone)]
pub enum Scale {
HO,
N,
O,
G,
}
impl fmt::Display for Scale {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Scale::HO => write!(f,"HO"),
Scale::N => write!(f,"N"),
Scale::O => write!(f,"O"),
Scale::G => write!(f,"G"),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub enum BZSegment {
S1(u32,f64,f64,f64,f64,f64),
S2(u32,u32,f64,f64,f64,f64,f64,f64,f64),
C1(u32,f64,f64,f64,f64,f64,f64),
C2(u32,u32,f64,f64,f64,f64,f64,f64,f64),
}
impl fmt::Display for BZSegment {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BZSegment::S1(a,b,c,d,e,f) =>
write!(fp,"<#BZSegment::S1({},{},{},{},{},{})>",a,b,c,d,e,f),
BZSegment::S2(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#BZSegment::S1({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
BZSegment::C1(a,b,c,d,e,f,g) =>
write!(fp,"<#BZSegment::C1({},{},{},{},{},{},{})>",
a,b,c,d,e,f,g),
BZSegment::C2(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#BZSegment::C2({},{},{},{},{},{},{},{},{})>",
a,b,e,d,e,f,g,h,i),
}
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct BZSegments {
elements: Vec<BZSegment>,
}
impl fmt::Display for BZSegments {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fp,"<#BZSegments {} elements>",self.elements.len())
}
}
impl BZSegments {
pub fn new() -> Self {
Self {elements: Vec::new()}
}
pub fn AppendBZSeg(e: BZSegment, mut b: BZSegments) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for BZSegments {
type Output = BZSegment;
fn index(&self, i: usize) -> &BZSegment {&self.elements[i]}
}
#[derive(Debug, PartialEq, Clone)]
pub struct BZLSegments {
elements: Vec<StructureBodyElement>,
}
impl BZLSegments {
pub fn new() -> Self {
Self{elements: Vec::new()}
}
pub fn Append(e: StructureBodyElement, mut b:BZLSegments) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl fmt::Display for BZLSegments {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#BZLSegments {} elements>", self.elements.len())
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct FBlockElement(f64,f64,u32);
impl fmt::Display for FBlockElement {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#FBlockElement {} {} {}>",self.0,self.1,self.2)
}
}
#[derive(Debug, PartialEq, Clone)]
pub struct FBlock {
elements: Vec<FBlockElement>
}
impl fmt::Display for FBlock {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#FBlock {} elements>", self.elements.len())
}
}
impl FBlock {
pub fn new() -> Self {
Self{ elements: Vec::new()}
}
pub fn Append(e: FBlockElement, mut b: FBlock) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for FBlock {
type Output = FBlockElement;
fn index(&self, i: usize) -> &FBlockElement {&self.elements[i]}
}
#[derive(Debug, PartialEq, Clone)]
pub enum StructureBodyElement {
D(f64,f64),
L(u32,u32,f64,f64,f64,u32,f64,f64,u32),
M(u32,u32,f64,f64,f64,u32,f64,f64,u32,u32),
F(u32,u32,f64,u32,Option<u32>,FBlock),
A(u32,u32,f64,f64,f64,f64,u32,f64,f64),
B(u32,u32,f64,f64,f64,u32,f64,f64,u32,u32),
Q(u32,u32,f64,f64,f64,u32,f64,f64,u32),
G(u32,u32,f64,f64,f64,f64,u32),
Y(u32,u32,f64,u32,u32,FBlock),
Z(u32,f64,f64,f64,u32,f64,String),
H(u32,u32,f64,f64,f64,f64,f64,f64,f64,f64,BZLSegments),
}
impl fmt::Display for StructureBodyElement {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
StructureBodyElement::D(a,b) =>
write!(fp, "<#StructureBodyElement::D({},{})>",a,b),
StructureBodyElement::L(a,b,c,d,e,f,g,h,i) =>
write!(fp, "<#StructureBodyElement::L({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
StructureBodyElement::M(a,b,c,d,e,f,g,h,i,j) =>
write!(fp, "<#StructureBodyElement::M({},{},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i,j),
StructureBodyElement::F(a,b,c,d,e,f) =>
write!(fp, "<#StructureBodyElement::F({},{},{},{},{},{})>",
a,b,c,d,
match e {
None => String::from("None"),
Some(v) => format!("Some({})", v),
},f),
StructureBodyElement::A(a,b,c,d,e,f,g,h,i) =>
write!(fp, "<#StructureBodyElement::A({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
StructureBodyElement::B(a,b,c,d,e,f,g,h,i,j) =>
write!(fp, "<#StructureBodyElement::B({},{},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i,j),
StructureBodyElement::Q(a,b,c,d,e,f,g,h,i) =>
write!(fp, "<#StructureBodyElement::Q({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
StructureBodyElement::G(a,b,c,d,e,f,g) =>
write!(fp, "<#StructureBodyElement::G({},{},{},{},{},{},{})>",
a,b,c,d,e,f,g),
StructureBodyElement::Y(a,b,c,d,e,f) =>
write!(fp, "<#StructureBodyElement::Y({},{},{},{},{},{})>",
a,b,c,d,e,f),
StructureBodyElement::Z(a,b,c,d,e,f,g) =>
write!(fp, "<#StructureBodyElement::Z({},{},{},{},{},{},{})>",
a,b,c,d,e,f,g),
StructureBodyElement::H(a,b,c,d,e,f,g,h,i,j,k) =>
write!(fp, "<#StructureBodyElement::H({},{},{},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i,j,k),
}
}
}
#[derive(Debug, Clone, PartialEq, Default)]
pub struct StructureBody {
elements: Vec<StructureBodyElement>,
}
impl fmt::Display for StructureBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#StructureBody {} elements>", self.elements.len())
}
}
impl StructureBody {
pub fn new() -> Self {
Self {elements: Vec::new()}
}
pub fn Append(e: StructureBodyElement, mut b: StructureBody) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for StructureBody {
type Output = StructureBodyElement;
fn index(&self, i: usize) -> &StructureBodyElement {&self.elements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub struct BZRLineBody {
elements: Vec<StructureBodyElement>,
}
impl fmt::Display for BZRLineBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#BZRLineBody {} elements>", self.elements.len())
}
}
impl BZRLineBody {
pub fn new() -> Self {
Self{ elements: Vec::new()}
}
pub fn Append(e: StructureBodyElement, mut b: BZRLineBody) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for BZRLineBody {
type Output = StructureBodyElement;
fn index(&self, i: usize) -> &StructureBodyElement {&self.elements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub struct CornuBodyElement(u32,u32,f64,f64,f64,f64,f64,f64,f64,f64,f64,
BZSegments);
impl fmt::Display for CornuBodyElement {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fp,"<#CornuBodyElement {},{},{},{},{},{},{},{},{},{},{},{}>",
self.0,self.1,self.2,self.3,self.4,self.5,self.6,self.7,self.8,
self.9,self.10,self.11)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct CornuBody {
trackends: Vec<TrackBodyElement>,
trackelements: Vec<CornuBodyElement>,
}
impl fmt::Display for CornuBody {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(fp,"<#CornuBody {} elements>",
self.trackelements.len())
}
}
impl CornuBody {
pub fn new() -> Self {
Self{ trackends: Vec::new(), trackelements: Vec::new(),}
}
pub fn AppendTrack(e: TrackBodyElement, mut b: CornuBody) -> Self {
b.trackends.insert(0,e);
b
}
pub fn AppendCornu(e: CornuBodyElement, mut b: CornuBody) -> Self {
b.trackelements.insert(0,e);
b
}
pub fn TrackEndsLen(&self) -> usize {self.trackends.len()}
pub fn TrackEnd(&self, i: usize) -> &TrackBodyElement {&self.trackends[i]}
pub fn len(&self) -> usize {self.trackelements.len()}
}
impl Index<usize> for CornuBody {
type Output = CornuBodyElement;
fn index(&self, i: usize) -> &CornuBodyElement {&self.trackelements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub enum FloatOrString {
Float(f64),
String(String),
}
impl fmt::Display for FloatOrString {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FloatOrString::Float(flo) => write!(f,"{}",flo),
FloatOrString::String(s) => write!(f,"{}",s),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TrackBodyElement {
T1(u32,f64,f64,f64,Option<TrackBodySubElement>),
T4(u32,u32,f64,f64,f64,TrackBodySubElement),
E1(f64,f64,f64,Option<TrackBodySubElement>),
E4(u32,f64,f64,f64,TrackBodySubElement),
}
impl fmt::Display for TrackBodyElement {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TrackBodyElement::T1(a,b,c,d,None) =>
write!(fp,"<#TrackBodyElement T1({},{},{},{})>",a,b,c,d),
TrackBodyElement::T1(a,b,c,d,Some(e)) =>
write!(fp,"<#TrackBodyElement T1({},{},{},{},{})>",
a,b,c,d,e),
TrackBodyElement::T4(a,b,c,d,e,f) =>
write!(fp,"<#TrackBodyElement T4({},{},{},{},{},{})>",
a,b,c,d,e,f),
TrackBodyElement::E1(a,b,c,None) =>
write!(fp,"<#TrackBodyElement E1({},{},{})>",a,b,c),
TrackBodyElement::E1(a,b,c,Some(d)) =>
write!(fp,"<#TrackBodyElement E1({},{},{},{})>",a,b,c,d),
TrackBodyElement::E4(a,b,c,d,e) =>
write!(fp,"<#TrackBodyElement E4({},{},{},{},{})>",a,b,c,d,e),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TrackBodySubElement {
T1(u32,f64,f64,Option<FloatOrString>),
T4(u32,f64,f64,FloatOrString,f64,u32,u32,u32,f64),
}
impl fmt::Display for TrackBodySubElement {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TrackBodySubElement::T1(a,b,c,None) =>
write!(fp,"<#TrackBodySubElement T1({},{},{})>",a,b,c),
TrackBodySubElement::T1(a,b,c,Some(d)) =>
write!(fp,"<#TrackBodySubElement T1({},{},{},{})>",a,b,c,d),
TrackBodySubElement::T4(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#TrackBodySubElement T4({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TrackBody {
elements: Vec<TrackBodyElement>,
}
impl fmt::Display for TrackBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#TrackBody {} elements>",self.elements.len())
}
}
impl TrackBody {
pub fn new() -> Self {
Self{ elements: Vec::new(),}
}
pub fn AppendTrack(e:TrackBodyElement, mut b: TrackBody) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for TrackBody {
type Output = TrackBodyElement;
fn index(&self, i: usize) -> &TrackBodyElement {&self.elements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub struct BezierBody {
elements: Vec<BezierBodyElement>,
}
impl fmt::Display for BezierBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#BezierBody {} elements>", self.elements.len())
}
}
impl BezierBody {
pub fn new() -> Self {
Self {elements: Vec::new()}
}
pub fn Append(e: BezierBodyElement, mut b: BezierBody) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for BezierBody {
type Output = BezierBodyElement;
fn index(&self, i: usize) -> &BezierBodyElement {&self.elements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub enum BezierBodyElement {
Curve1(u32,f64,f64,f64,f64,f64,f64),
Curve2(u32,u32,f64,f64,f64,f64,f64,f64,f64),
Straight1(u32,f64,f64,f64,f64,f64),
Straight2(u32,u32,f64,f64,f64,f64,f64,f64,f64),
T1(u32,f64,f64,f64,Option<TrackBodySubElement>),
T4(u32,u32,f64,f64,f64,TrackBodySubElement),
E1(f64,f64,f64,Option<TrackBodySubElement>),
E4(u32,f64,f64,f64,TrackBodySubElement),
}
impl fmt::Display for BezierBodyElement {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BezierBodyElement::Curve1(a,b,c,d,e,f,g) =>
write!(fp,"<#BezierBodyElement Curve1({},{},{},{},{},{},{})>",
a,b,c,d,e,f,g),
BezierBodyElement::Curve2(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#BezierBodyElement Curve2({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
BezierBodyElement::Straight1(a,b,c,d,e,f) =>
write!(fp,"<#BezierBodyElement Straight1({},{},{},{},{},{})>",
a,b,c,d,e,f),
BezierBodyElement::Straight2(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#BezierBodyElement Straight2({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
BezierBodyElement::T1(a,b,c,d,None) =>
write!(fp,"<#BezierBodyElement T1({},{},{},{})>",a,b,c,d),
BezierBodyElement::T1(a,b,c,d,Some(e)) =>
write!(fp,"<#BezierBodyElement T1({},{},{},{},{})>",
a,b,c,d,e),
BezierBodyElement::T4(a,b,c,d,e,f) =>
write!(fp,"<#BezierBodyElement T4({},{},{},{},{},{})>",
a,b,c,d,e,f),
BezierBodyElement::E1(a,b,c,None) =>
write!(fp,"<#BezierBodyElement E1({},{},{})>",a,b,c),
BezierBodyElement::E1(a,b,c,Some(d)) =>
write!(fp,"<#BezierBodyElement E1({},{},{},{})>",a,b,c,d),
BezierBodyElement::E4(a,b,c,d,e) =>
write!(fp,"<#BezierBodyElement E4({},{},{},{},{})>",a,b,c,d,e),
}
}
}
impl BezierBodyElement {
pub fn MakeTrackEnd(e:TrackBodyElement) -> BezierBodyElement {
match e {
TrackBodyElement::T1(a,b,c,d,e) =>
BezierBodyElement::T1(a,b,c,d,e),
TrackBodyElement::T4(a2,b,c,d,e,f) =>
BezierBodyElement::T4(a2,b,c,d,e,f),
TrackBodyElement::E1(a,b,c,f) =>
BezierBodyElement::E1(a,b,c,f),
TrackBodyElement::E4(a,b,c,f,g) =>
BezierBodyElement::E4(a,b,c,f,g),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct IntegerList {
elements: Vec<u32>,
}
impl fmt::Display for IntegerList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#IntegerList")?;
for v in self.elements.iter() {
write!(f, " {}",v)?;
}
write!(f,">")
}
}
impl IntegerList {
pub fn new() -> Self {
Self { elements: Vec::new() }
}
pub fn Append(e: u32, mut b: IntegerList) -> Self {
b.elements.insert(0,e);
b
}
pub fn len(&self) -> usize {self.elements.len()}
}
impl Index<usize> for IntegerList {
type Output = u32;
fn index(&self, i: usize) -> &u32 {&self.elements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub struct TurnoutBody {
turnout_elements: Vec<TurnoutBodyElement>,
struct_elements: Vec<StructureBodyElement>,
}
impl fmt::Display for TurnoutBody {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#TurnoutBody {} turnout elements {} structure elements>",
self.turnout_elements.len(), self.struct_elements.len())
}
}
impl TurnoutBody {
pub fn new() -> Self {
Self { turnout_elements: Vec::new(), struct_elements: Vec::new(),}
}
pub fn AppendTurnoutBodyElement(e: TurnoutBodyElement,
mut b: TurnoutBody) -> Self {
b.turnout_elements.insert(0,e);
b
}
pub fn AppendStructureBodyElement(e: StructureBodyElement,
mut b: TurnoutBody) -> Self {
b.struct_elements.insert(0,e);
b
}
pub fn TurnoutElementsLen(&self) -> usize {self.turnout_elements.len()}
pub fn TurnoutElement(&self, i: usize) -> &TurnoutBodyElement {
&self.turnout_elements[i]
}
pub fn StructureElementsLen(&self) -> usize {self.struct_elements.len()}
}
impl Index<usize> for TurnoutBody {
type Output = StructureBodyElement;
fn index(&self, i: usize) -> &StructureBodyElement {&self.struct_elements[i]}
}
#[derive(Debug, Clone, PartialEq)]
pub enum TurnoutBodyElement {
D(f64,f64),
P(String,IntegerList),
S1(u32,f64,f64,f64,f64,f64),
S2(u32,u32,f64,f64,f64,f64,f64,f64,f64),
C1(u32,f64,f64,f64,f64,f64,f64),
C2(u32,u32,f64,f64,f64,f64,f64,f64,f64),
J1(u32,f64,f64,f64,f64,f64,f64,f64,f64,u32),
J2(u32,u32,f64,f64,f64,f64,f64,f64,f64,f64,f64,u32),
T1(u32,f64,f64,f64,Option<TrackBodySubElement>),
T4(u32,u32,f64,f64,f64,TrackBodySubElement),
E1(f64,f64,f64,Option<TrackBodySubElement>),
E4(u32,f64,f64,f64,TrackBodySubElement),
}
impl fmt::Display for TurnoutBodyElement {
fn fmt(&self, fp: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
TurnoutBodyElement::D(a,b) =>
write!(fp,"<#TurnoutBodyElement D({},{})>",a,b),
TurnoutBodyElement::P(s,iList) =>
write!(fp,"<#TurnoutBodyElement P({},{})>",s,iList),
TurnoutBodyElement::S1(a,b,c,d,e,f) =>
write!(fp,"<#TurnoutBodyElement S1({},{},{},{},{},{})>",
a,b,c,d,e,f),
TurnoutBodyElement::S2(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#TurnoutBodyElement S2({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
TurnoutBodyElement::C1(a,b,c,d,e,f,g) =>
write!(fp,"<#TurnoutBodyElement C1({},{},{},{},{},{},{})>",
a,b,c,d,e,f,g),
TurnoutBodyElement::C2(a,b,c,d,e,f,g,h,i) =>
write!(fp,"<#TurnoutBodyElement C2({},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i),
TurnoutBodyElement::J1(a,b,c,d,e,f,g,h,i,j) =>
write!(fp,"<#TurnoutBodyElement J1({},{},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i,j),
TurnoutBodyElement::J2(a,b,c,d,e,f,g,h,i,j,k,l) =>
write!(fp,"<#TurnoutBodyElement J2({},{},{},{},{},{},{},{},{},{},{},{})>",
a,b,c,d,e,f,g,h,i,j,k,l),
TurnoutBodyElement::T1(a,b,c,d,None) =>
write!(fp,"<#TurnoutBodyElement T1({},{},{},{})>",a,b,c,d),
TurnoutBodyElement::T1(a,b,c,d,Some(e)) =>
write!(fp,"<#TurnoutBodyElement T1({},{},{},{},{})>",
a,b,c,d,e),
TurnoutBodyElement::T4(a,b,c,d,e,f) =>
write!(fp,"<#TurnoutBodyElement T4({},{},{},{},{},{})>",
a,b,c,d,e,f),
TurnoutBodyElement::E1(a,b,c,None) =>
write!(fp,"<#TurnoutBodyElement E1({},{},{})>",a,b,c),
TurnoutBodyElement::E1(a,b,c,Some(d)) =>
write!(fp,"<#TurnoutBodyElement E1({},{},{},{})>",a,b,c,d),
TurnoutBodyElement::E4(a,b,c,d,e) =>
write!(fp,"<#TurnoutBodyElement E4({},{},{},{},{})>",a,b,c,d,e),
}
}
}
impl TurnoutBodyElement {
pub fn MakeTurnoutEnd(tbelt: TrackBodyElement) -> Self {
match tbelt {
TrackBodyElement::T1(a,b,c,d,e) =>
TurnoutBodyElement::T1(a,b,c,d,e),
TrackBodyElement::T4(a2,b,c,d,e,f) =>
TurnoutBodyElement::T4(a2,b,c,d,e,f),
TrackBodyElement::E1(a,b,c,f) =>
TurnoutBodyElement::E1(a,b,c,f),
TrackBodyElement::E4(a,b,c,f,g) =>
TurnoutBodyElement::E4(a,b,c,f,g),
}
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct CarAux(u32,u32,f64,f64,f64,TrackBody);
impl fmt::Display for CarAux {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "<#CarAux {} {} {} {} {} {}>",
self.0,self.1,self.2,self.3,self.4,self.5)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct Aspect(String,String);
impl fmt::Display for Aspect {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,"<#Aspect {} {}>",self.0, self.1)
}
}
#[derive(Debug, Clone, PartialEq)]
pub struct AspectList {
aspects: Vec<Aspect>,
}
impl fmt::Display for AspectList {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f,"<#AspectList {} aspects>",self.aspects.len())
}
}
impl AspectList {
pub fn new() -> Self {
Self{aspects: Vec::new()}
}
pub fn AddAspect(mut b: AspectList, a: String, s: String) -> Self {
b.aspects.insert(0,Aspect(a,s));
b
}
pub fn len(&self) -> usize {self.aspects.len()}
}
impl Index<usize> for AspectList {
type Output = Aspect;
fn index(&self, i: usize) -> &Aspect {&self.aspects[i]}
}