refactor using Enum

This commit is contained in:
Denis-Cosmin Nutiu 2024-10-24 21:27:27 +03:00
parent 8ad7f5c305
commit 283efb0b1f
2 changed files with 54 additions and 101 deletions

View file

@ -1,100 +1,51 @@
use std::fmt; use std::fmt;
use std::fmt::Formatter; use std::fmt::Formatter;
use std::ops::Deref;
pub trait Line: fmt::Display {
fn is_differing(&self) -> bool;
}
/// Line represents a non-differing line.
pub(crate) struct MatchedLine {
line_number: i32,
line: String,
}
impl MatchedLine {
/// Constructs a new Line instance
pub fn new(line_number: i32, line: String) -> MatchedLine {
MatchedLine { line_number, line }
}
/// get_line returns the line.
pub fn get_line(&self) -> &String {
&self.line
}
}
impl fmt::Display for MatchedLine {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, r#"{}. {}"#, self.line_number, self.get_line(),)
.expect("Failed to write MatchedLine");
writeln!(f)
}
}
impl Line for MatchedLine {
fn is_differing(&self) -> bool {
false
}
}
/// A line difference is represented by the Difference struct.
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct DifferingLine { pub(crate) struct MissingLineIndicator {
line_number: i32, pub value: String
missing_line_indicator: String,
left_line: String,
right_line: String,
} }
impl DifferingLine { impl Default for MissingLineIndicator {
/// Constructs a new difference instance. fn default() -> Self {
pub fn new(line_number: i32, left_line: String, right_line: String) -> DifferingLine { MissingLineIndicator{
DifferingLine { value: String::from("<missing line>")
line_number,
missing_line_indicator: String::from("<missing line>"),
left_line: left_line.into(),
right_line: right_line.into(),
} }
} }
/// Returns the left line of the difference.
#[allow(dead_code)]
pub fn left_line(&self) -> &String {
if self.left_line.deref() == "" {
return &self.missing_line_indicator;
}
&self.left_line
}
/// Returns the right line of the difference.
#[allow(dead_code)]
pub fn right_line(&self) -> &String {
if self.right_line.deref() == "" {
return &self.missing_line_indicator;
}
&self.right_line
}
} }
impl fmt::Display for DifferingLine { /// The line enum models a file line.
pub(crate) enum Line {
/// MatchedLine represents a line that matches when comparing the files.
///
/// MatchedLine(line_number, line)
MatchedLine(i32, String),
/// DifferingLine represents a line that does not match its counterpart line.
///
/// DifferingLine(line_number, left_line, right_line)
DifferingLine(i32, String, String),
}
impl fmt::Display for Line {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!( match self {
f, Line::MatchedLine(line_number, line) => {
r#" - {} write!(f, r#"{}. {}"#, line_number, line,).expect("Failed to write MatchedLine");
{}. ---- writeln!(f)
+ {}"#, }
self.left_line(), Line::DifferingLine(line_number, left_line, right_line) => {
self.line_number, write!(
self.right_line() f,
) r#" - {left_line}
.expect("Failed to write DifferingLines"); {line_number}. ----
writeln!(f) + {right_line}"#,
left_line = left_line,
line_number = line_number,
right_line = right_line
)
.expect("Failed to write DifferingLines");
writeln!(f)
}
}
} }
} }
impl Line for DifferingLine {
fn is_differing(&self) -> bool {
true
}
}

View file

@ -1,27 +1,27 @@
use crate::line::{DifferingLine, Line, MatchedLine}; use crate::line::{Line, MissingLineIndicator};
use itertools::Itertools; use itertools::Itertools;
use std::fs::read_to_string; use std::fs::read_to_string;
use std::ops::Deref;
mod line; mod line;
/// Gets the lines of two given texts /// Gets the lines of two given texts
/// ///
/// It returns a [`Vec<Box<dyn Line>>`] /// It returns a [`Vec<Box<Line>>`]
fn get_lines(left_text: &String, right_text: &String) -> Vec<Box<dyn Line>> { fn get_lines(left_text: &String, right_text: &String) -> Vec<Line> {
left_text left_text
.lines() .lines()
.map(String::from) .map(String::from)
.zip_longest(right_text.lines().map(String::from)) .zip_longest(right_text.lines().map(String::from))
.enumerate() .enumerate()
.map(|(line, item)| -> Box<dyn Line> { .map(|(line_number, item)| -> Line {
let left = item.clone().left().unwrap_or(String::from("")); let missing_line_indicator: MissingLineIndicator = Default::default();
let right = item.right().unwrap_or(String::from("")); let left = item.clone().left().unwrap_or(missing_line_indicator.value.clone());
let right = item.right().unwrap_or(missing_line_indicator.value);
if left != right { if left != right {
Box::new(DifferingLine::new(line as i32 + 1, left, right)) Line::DifferingLine(line_number as i32 + 1, left, right)
} else { } else {
Box::new(MatchedLine::new(line as i32 + 1, left)) Line::MatchedLine(line_number as i32 + 1, left)
} }
}) })
.collect() .collect()
@ -31,14 +31,16 @@ fn main() {
let left_file = read_to_string("a.txt").expect("Left file not found"); let left_file = read_to_string("a.txt").expect("Left file not found");
let right_file = read_to_string("b.txt").expect("Right file not found"); let right_file = read_to_string("b.txt").expect("Right file not found");
let lines: Vec<Box<dyn Line>> = get_lines(&left_file, &right_file); let lines: Vec<Line> = get_lines(&left_file, &right_file);
let mut differences_counter: i32 = 0; let mut differences_counter: i32 = 0;
for line in lines.iter() { for line in lines.iter() {
let line = line.deref();
print!("{}", line); print!("{}", line);
if line.is_differing() { match line {
differences_counter += 1; Line::MatchedLine(_, _) => {}
Line::DifferingLine(_, _, _) => {
differences_counter += 1
}
} }
} }
println!(); println!();