FastWaveBackend/src/main.rs

249 lines
7.7 KiB
Rust
Raw Normal View History

2022-04-14 04:50:37 +00:00
use std::io::prelude::*;
use std::io;
use std::fs::File;
2022-05-18 02:04:32 +00:00
use std::collections::BTreeMap;
2022-05-19 07:44:24 +00:00
use chrono::prelude::*;
use std::rc::Rc;
2022-04-14 04:50:37 +00:00
use num::*;
use clap::Parser;
#[derive(Parser)]
struct Cli {
/// The path to the file to read
#[clap(parse(from_os_str))]
path: std::path::PathBuf}
2022-04-14 04:50:37 +00:00
2022-05-19 07:44:24 +00:00
// TODO: implement any timescales greater than a second
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
enum Timescale {ps, ns, us, ms, s, unit}
2022-05-19 07:44:24 +00:00
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
struct Scope_Idx(usize);
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
struct Signal_Idx(usize);
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
2022-05-23 23:19:17 +00:00
struct Version(String);
2022-05-19 07:44:24 +00:00
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
struct Metadata {
2022-05-23 23:19:17 +00:00
date : Option<DateTime<Utc>>,
version : Option<Version>,
2022-05-23 03:00:03 +00:00
timescale : Timescale}
2022-05-19 07:44:24 +00:00
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
2022-05-19 07:44:24 +00:00
enum SignalGeneric{
2022-05-23 03:00:03 +00:00
Signal{
name : String,
timeline : BTreeMap<BigInt, BigInt>,
scope_parent : Scope_Idx},
SignalAlias{
name : String,
signal_alias : Signal_Idx}
}
2022-05-18 02:04:32 +00:00
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
2022-05-19 07:44:24 +00:00
struct Scope {
name : String,
child_signals : Vec<Signal_Idx>,
child_scopes : Vec<Scope_Idx>}
2022-05-19 07:44:24 +00:00
2022-05-23 03:00:03 +00:00
#[derive(Debug)]
2022-05-19 07:44:24 +00:00
struct VCD {
metadata : Metadata,
all_signals : Vec<SignalGeneric>,
// the root scope should always be placed at index 0
all_scopes : Vec<Scope>}
2022-05-23 23:19:17 +00:00
// TODO : Date_PArser_State -> Parse_Date
#[derive(Debug)]
2022-05-23 03:00:03 +00:00
enum Date_Parser_State {Weekday, Month, Day, HHMMSS, Year, End}
2022-05-23 23:19:17 +00:00
#[derive(Debug)]
enum Version_Parser_State {Parsing, Done}
2022-05-23 03:00:03 +00:00
2022-05-22 00:40:46 +00:00
#[derive(Debug)]
enum VCD_Parser_State {
Begin,
Date(Date_Parser_State),
2022-05-23 23:19:17 +00:00
Parse_Version(Version_Parser_State),
2022-05-22 00:40:46 +00:00
Parse_Signal_Tree,
Parse_Signal_Values}
struct DateBuffer {
2022-05-23 03:00:03 +00:00
Weekday : Option<String>,
Month : Option<String>,
Day : Option<String>,
HHMMSS : Option<String>,
Year : Option<String>}
struct VCD_Parser<'a> {
vcd_parser_state : VCD_Parser_State,
date_parser_state : Date_Parser_State,
date_buffer : DateBuffer,
2022-05-22 00:40:46 +00:00
vcd : &'a mut VCD,
2022-05-23 03:00:03 +00:00
curr_scope : Option<&'a Scope>,
curr_parent_scope : Option<&'a Scope>}
impl VCD {
pub fn new() -> Self {
let dt = Utc
.datetime_from_str("Thu Jan 1 00:00:00 1970", "%a %b %e %T %Y")
.unwrap();
let metadata = Metadata {
2022-05-23 23:19:17 +00:00
date : None,
version : None,
2022-05-23 03:00:03 +00:00
timescale : Timescale::unit};
let signal = Vec::<SignalGeneric>::new();
VCD {
metadata : metadata,
all_signals : Vec::<SignalGeneric>::new(),
all_scopes : Vec::<Scope>::new()}}}
impl<'a> VCD_Parser<'a> {
2022-05-23 03:00:03 +00:00
pub fn new(vcd : &'a mut VCD) -> Self {
let date_buffer = DateBuffer{
Weekday : None,
Month : None,
Day : None,
HHMMSS : None,
Year : None
};
VCD_Parser {
vcd_parser_state : VCD_Parser_State ::Begin,
date_parser_state : Date_Parser_State::Weekday,
date_buffer : date_buffer,
vcd : vcd,
curr_scope : None,
curr_parent_scope : None
}
}
pub fn parse_word(&mut self, word : &str) -> Result<(), String> {
let mut state = &mut self.vcd_parser_state;
2022-05-23 03:00:03 +00:00
let t = &self.vcd;
match state {
2022-05-23 03:00:03 +00:00
VCD_Parser_State::Begin =>
match word {
2022-05-23 03:00:03 +00:00
"$date" => {*state = VCD_Parser_State::Date(Date_Parser_State::Weekday); Ok(())}
_ => Err(format!("unsure what to do with {word:?} in state `{state:?}`"))
}
VCD_Parser_State::Date(_) => self.parse_date(word),
2022-05-23 23:19:17 +00:00
VCD_Parser_State::Parse_Version(_) => self.parse_date(word),
2022-05-23 03:00:03 +00:00
// TODO : Enable the following in production
// _ => Err(format!("parser in bad state : {state:?}"))TODO : Disable the following in production
// TODO : Disable the following in production
_ => Err(format!("parser in bad state : {state:?}; {t:?}"))
}
}
2022-05-19 07:44:24 +00:00
pub fn parse_date(&mut self, word : &str) -> Result<(), String> {
let mut state = &mut self.vcd_parser_state;
match state {
VCD_Parser_State::Date(Date_Parser_State::Weekday) =>
{
2022-05-23 03:00:03 +00:00
self.date_buffer.Weekday = Some(word.to_string());
*state = VCD_Parser_State::Date(Date_Parser_State::Month);
Ok(())
}
VCD_Parser_State::Date(Date_Parser_State::Month) =>
{
2022-05-23 03:00:03 +00:00
self.date_buffer.Month = Some(word.to_string());
*state = VCD_Parser_State::Date(Date_Parser_State::Day);
Ok(())
}
2022-05-22 00:40:46 +00:00
VCD_Parser_State::Date(Date_Parser_State::Day) =>
{
2022-05-23 03:00:03 +00:00
self.date_buffer.Day = Some(word.to_string());
2022-05-22 00:40:46 +00:00
*state = VCD_Parser_State::Date(Date_Parser_State::HHMMSS);
Ok(())
}
VCD_Parser_State::Date(Date_Parser_State::HHMMSS) =>
{
2022-05-23 03:00:03 +00:00
self.date_buffer.HHMMSS = Some(word.to_string());
2022-05-22 00:40:46 +00:00
*state = VCD_Parser_State::Date(Date_Parser_State::Year);
Ok(())
}
VCD_Parser_State::Date(Date_Parser_State::Year) =>
{
2022-05-23 03:00:03 +00:00
self.date_buffer.Year = Some(word.to_string());
2022-05-22 00:40:46 +00:00
// now that we've successfully parsed all the date information,
2022-05-23 03:00:03 +00:00
// we store it to the metadata.date struct
let weekday = &self.date_buffer.Weekday.as_ref().unwrap();
let month = &self.date_buffer.Month.as_ref().unwrap();
let day = &self.date_buffer.Day.as_ref().unwrap();
let hhmmss = &self.date_buffer.HHMMSS.as_ref().unwrap();
let year = &self.date_buffer.Year.as_ref().unwrap();
2022-05-22 00:40:46 +00:00
let date = &format!("{weekday} {month} {day} {hhmmss} {year}")[..];
2022-05-23 03:00:03 +00:00
let dt = Utc.datetime_from_str(date, "%a %b %e %T %Y")
.expect(&format!("invalid date {date}")[..]);
2022-05-22 00:40:46 +00:00
2022-05-23 23:19:17 +00:00
self.vcd.metadata.date = Some(dt);
2022-05-22 00:40:46 +00:00
2022-05-23 03:00:03 +00:00
*state = VCD_Parser_State::Date(Date_Parser_State::End);
2022-05-22 00:40:46 +00:00
Ok(())
}
2022-05-23 03:00:03 +00:00
VCD_Parser_State::Date(Date_Parser_State::End) =>
{
let expected_word = "$end";
match word {
2022-05-23 23:19:17 +00:00
expected_word => {
*state = VCD_Parser_State::Parse_Version(Version_Parser_State::Parsing);
Ok(())
}
2022-05-23 03:00:03 +00:00
_ => Err(format!("expected `{expected_word}` but found `{word}`"))
}
}
2022-05-22 00:40:46 +00:00
_ => Err(format!("{state:?} should be unreachable within DateParser.")),
}
}
}
2022-04-14 04:50:37 +00:00
2022-05-23 03:00:03 +00:00
fn yield_word_and_apply(file : File, mut f : impl FnMut(&str) -> Result<(), String>) {
2022-04-14 04:50:37 +00:00
let mut reader = io::BufReader::new(file);
let mut buffer = String::new();
let mut EOF = false;
let line_chunk_size = 25;
2022-04-14 04:50:37 +00:00
while {!EOF} {
for _ in 0..line_chunk_size {
let bytes_read = reader.read_line(&mut buffer).unwrap();
if bytes_read == 0 {
EOF = true;
break
}
}
let words = buffer.split_ascii_whitespace();
for word in words {
2022-05-23 03:00:03 +00:00
f(word).unwrap();
}
buffer.clear();
2022-04-14 04:50:37 +00:00
}
}
fn main() -> std::io::Result<()> {
let args = Cli::parse();
2022-05-19 07:44:24 +00:00
let file = File::open(&args.path)?;
2022-05-23 03:00:03 +00:00
let mut vcd = VCD::new();
let mut parser = VCD_Parser::new(&mut vcd);
yield_word_and_apply(file, |word| {parser.parse_word(word)});
dbg!(&vcd);
2022-04-14 04:50:37 +00:00
Ok(())
}