mirror of
https://github.com/132nd-vWing/tacview-splitter.git
synced 2026-08-26 07:48:37 +02:00
more error handling
This commit is contained in:
+1
-1
@@ -18,7 +18,7 @@ fn main() {
|
|||||||
fn main_inner() -> Result<(), Box<dyn std::error::Error>> {
|
fn main_inner() -> Result<(), Box<dyn std::error::Error>> {
|
||||||
let (input_filename, is_zip) = reader::find_input_file()?;
|
let (input_filename, is_zip) = reader::find_input_file()?;
|
||||||
println!("Processing {}", input_filename);
|
println!("Processing {}", input_filename);
|
||||||
let lines = reader::read_data(&input_filename, is_zip);
|
let lines = reader::read_data(&input_filename, is_zip)?;
|
||||||
let (header, body) = processor::split_into_header_and_body(&lines);
|
let (header, body) = processor::split_into_header_and_body(&lines);
|
||||||
|
|
||||||
let coalition_per_line = processor::divide_body_by_coalition(body);
|
let coalition_per_line = processor::divide_body_by_coalition(body);
|
||||||
|
|||||||
+71
-22
@@ -1,31 +1,45 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
use std::fmt::Display;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::constants::{COMMENT, MINUS};
|
use crate::constants::{COMMENT, MINUS};
|
||||||
use crate::tacview::{Coalition, CoalitionIDs};
|
use crate::tacview::{Coalition, CoalitionIDs};
|
||||||
|
|
||||||
pub fn split_into_header_and_body<S: AsRef<str>>(lines: &[S]) -> (&[S], &[S]) {
|
pub fn split_into_header_and_body<S, E>(lines: &[S]) -> Result<(&[S], &[S]), ProcessingError>
|
||||||
|
where
|
||||||
|
S: AsRef<str>,
|
||||||
|
{
|
||||||
let mut i = 0;
|
let mut i = 0;
|
||||||
for line in lines {
|
for line in lines {
|
||||||
if line.as_ref().chars().next().expect("malformed line") == COMMENT {
|
if line
|
||||||
|
.as_ref()
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.ok_or(ProcessingError::LineIsEmptyError)?
|
||||||
|
== COMMENT
|
||||||
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
(&lines[..i], &lines[i..])
|
Ok((&lines[..i], &lines[i..]))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn divide_body_by_coalition<S: AsRef<str> + Hash + Eq>(body: &[S]) -> Vec<Coalition> {
|
pub fn divide_body_by_coalition<S>(body: &[S]) -> Result<Vec<Coalition>, Box<dyn Error>>
|
||||||
|
where
|
||||||
|
S: AsRef<str> + Hash + Eq,
|
||||||
|
{
|
||||||
let mut result = vec![];
|
let mut result = vec![];
|
||||||
let mut coalition_ids: CoalitionIDs = CoalitionIDs::new();
|
let mut coalition_ids: CoalitionIDs = CoalitionIDs::new();
|
||||||
|
|
||||||
let mut old_line = Line::default();
|
let mut old_line = Line::default();
|
||||||
|
|
||||||
for line_s in body {
|
for line_s in body {
|
||||||
let processed = Line::process_line(old_line, line_s, &mut coalition_ids);
|
let processed = Line::process_line(old_line, line_s, &mut coalition_ids)?;
|
||||||
result.push(processed.coalition.clone());
|
result.push(processed.coalition.clone());
|
||||||
old_line = processed;
|
old_line = processed;
|
||||||
}
|
}
|
||||||
result
|
Ok(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Line {
|
struct Line {
|
||||||
@@ -39,17 +53,19 @@ impl Line {
|
|||||||
old_line: Line,
|
old_line: Line,
|
||||||
current_line: &'a S,
|
current_line: &'a S,
|
||||||
coalition_ids: &mut CoalitionIDs<'a>,
|
coalition_ids: &mut CoalitionIDs<'a>,
|
||||||
) -> Self {
|
) -> Result<Self, ProcessingError> {
|
||||||
let line_type = match old_line.continued {
|
let line_type = match old_line.continued {
|
||||||
true => old_line.line_type,
|
true => old_line.line_type,
|
||||||
false => LineType::find_type(current_line),
|
false => LineType::find_type(current_line)?,
|
||||||
};
|
};
|
||||||
|
|
||||||
match line_type {
|
match line_type {
|
||||||
LineType::Telemetry => Line::from_content(line_type, current_line, coalition_ids),
|
LineType::Telemetry => Ok(Line::from_content(line_type, current_line, coalition_ids)?),
|
||||||
LineType::Timestamp => Line::new(line_type, false, Coalition::All),
|
LineType::Timestamp => Ok(Line::new(line_type, false, Coalition::All)),
|
||||||
LineType::Destruction => Line::from_content(line_type, current_line, coalition_ids),
|
LineType::Destruction => {
|
||||||
LineType::Unknown => panic!(""),
|
Ok(Line::from_content(line_type, current_line, coalition_ids)?)
|
||||||
|
}
|
||||||
|
LineType::Unknown => Err(ProcessingError::UnknownLineType),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,11 +73,11 @@ impl Line {
|
|||||||
line_type: LineType,
|
line_type: LineType,
|
||||||
current_line: &'a S,
|
current_line: &'a S,
|
||||||
coalition_ids: &mut CoalitionIDs<'a>,
|
coalition_ids: &mut CoalitionIDs<'a>,
|
||||||
) -> Self {
|
) -> Result<Self, ProcessingError> {
|
||||||
let id = Self::get_id_from_line(current_line);
|
let id = Self::get_id_from_line(current_line)?;
|
||||||
let continued = Self::will_line_continue(current_line);
|
let continued = Self::will_line_continue(current_line);
|
||||||
let coalition = Self::assign_id_to_coalitions(coalition_ids, current_line, id);
|
let coalition = Self::assign_id_to_coalitions(coalition_ids, current_line, id);
|
||||||
Line::new(line_type, continued, coalition)
|
Ok(Line::new(line_type, continued, coalition))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assign_id_to_coalitions<'a, S: AsRef<str>>(
|
fn assign_id_to_coalitions<'a, S: AsRef<str>>(
|
||||||
@@ -82,8 +98,12 @@ impl Line {
|
|||||||
current_line.as_ref().ends_with('\\')
|
current_line.as_ref().ends_with('\\')
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_id_from_line<S: AsRef<str>>(line: &S) -> &str {
|
fn get_id_from_line<S: AsRef<str>>(line: &S) -> Result<&str, ProcessingError> {
|
||||||
line.as_ref().split_once(',').unwrap().0
|
Ok(line
|
||||||
|
.as_ref()
|
||||||
|
.split_once(',')
|
||||||
|
.ok_or(ProcessingError::CannotGetIDFromLine)?
|
||||||
|
.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(line_type: LineType, continued: bool, coalition: Coalition) -> Self {
|
fn new(line_type: LineType, continued: bool, coalition: Coalition) -> Self {
|
||||||
@@ -93,7 +113,9 @@ impl Line {
|
|||||||
coalition,
|
coalition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Line {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self::new(LineType::Unknown, false, Coalition::Unknown)
|
Self::new(LineType::Unknown, false, Coalition::Unknown)
|
||||||
}
|
}
|
||||||
@@ -108,14 +130,41 @@ enum LineType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl LineType {
|
impl LineType {
|
||||||
fn find_type<S: AsRef<str>>(line: &S) -> Self {
|
fn find_type<S: AsRef<str>>(line: &S) -> Result<Self, ProcessingError> {
|
||||||
let first_char = line.as_ref().chars().next().unwrap();
|
let first_char = line
|
||||||
|
.as_ref()
|
||||||
|
.chars()
|
||||||
|
.next()
|
||||||
|
.ok_or(ProcessingError::LineIsEmptyError)?;
|
||||||
if first_char == COMMENT {
|
if first_char == COMMENT {
|
||||||
Self::Timestamp
|
Ok(Self::Timestamp)
|
||||||
} else if first_char == MINUS {
|
} else if first_char == MINUS {
|
||||||
Self::Destruction
|
Ok(Self::Destruction)
|
||||||
} else {
|
} else {
|
||||||
LineType::Telemetry
|
Ok(LineType::Telemetry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum ProcessingError {
|
||||||
|
LineIsEmptyError,
|
||||||
|
UnknownLineType,
|
||||||
|
CannotSplitIntoHeaderAndBody,
|
||||||
|
CannotGetIDFromLine,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Error for ProcessingError {}
|
||||||
|
|
||||||
|
impl Display for ProcessingError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::LineIsEmptyError => write!(f, "line in tacview file is empty"),
|
||||||
|
Self::UnknownLineType => write!(f, "unknown line type in tacview file"),
|
||||||
|
Self::CannotSplitIntoHeaderAndBody => {
|
||||||
|
write!(f, "cannot split the file into header and body")
|
||||||
|
}
|
||||||
|
Self::CannotGetIDFromLine => write!(f, "cannot get unit ID from line"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-2
@@ -38,7 +38,10 @@ fn read_zip(buf: BufReader<File>) -> Result<Vec<String>, Error> {
|
|||||||
Ok(read_txt(inner_buf)?)
|
Ok(read_txt(inner_buf)?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_txt<T: BufRead>(buf: T) -> Result<Vec<String>, Error> {
|
fn read_txt(buf: impl BufRead) -> Result<Vec<String>, Error> {
|
||||||
let lines: Vec<String> = buf.lines().map(|l|).collect();
|
let lines: Vec<String> = buf
|
||||||
|
.lines()
|
||||||
|
.map(|l| l.expect("Could not read from the file"))
|
||||||
|
.collect();
|
||||||
Ok(lines)
|
Ok(lines)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user