Skip to content
This repository was archived by the owner on Apr 16, 2023. It is now read-only.

Commit 9193d66

Browse files
authored
Merge pull request #2 from CodeDead/feature/exporting
Feature/exporting
2 parents 3e37457 + 72d9298 commit 9193d66

File tree

8 files changed

+399
-46
lines changed

8 files changed

+399
-46
lines changed

Cargo.lock

Lines changed: 39 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ license-file = "LICENSE"
1212
[dependencies]
1313
iced = { git = "https://github.com/iced-rs/iced" }
1414
native-dialog = "0.6.3"
15+
serde = { version = "1.0", features = ["derive"] }
16+
serde_json = "1.0"
1517

1618
[profile.release]
1719
lto = true

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
![GitHub](https://img.shields.io/badge/language-Rust-green)
55
![GitHub](https://img.shields.io/github/license/CodeDead/text-diff-rs)
66

7-
![text-diff](https://i.imgur.com/PxbT90B.png)
7+
![text-diff](https://i.imgur.com/VrcSyMD.png)
88

99
`text-diff` can be used to compare two text files and output the difference between them. `text-diff` was written in `Rust` and offers a simple and intuitive user-interface for Windows, Linux and macOS.
1010

@@ -40,6 +40,8 @@ cargo run
4040
* [Rust](https://www.rust-lang.org/)
4141
* [iced](https://iced.rs/)
4242
* [native-dialog](https://github.com/balthild/native-dialog-rs)
43+
* [serde](https://serde.rs/)
44+
* [serde_json](https://serde.rs/)
4345

4446
## About
4547

src/main.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
use iced::window;
22
use iced::{Sandbox, Settings};
33

4-
mod view;
5-
mod style;
64
mod filereader;
5+
mod style;
6+
mod vector_comparer;
7+
mod vector_exporter;
8+
mod view;
9+
710
pub fn main() -> iced::Result {
811
view::ApplicationContext::run(Settings {
912
id: Some(String::from("text-diff")),

src/style.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,7 @@ mod dark {
383383
a: 0.8,
384384
..if is_checked { ACTIVE } else { SURFACE }
385385
}
386-
.into(),
386+
.into(),
387387
..self.active(is_checked)
388388
}
389389
}

src/vector_comparer.rs

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
pub trait IVectorComparer<T> {
2+
fn new(vec1: Vec<T>, vec2: Vec<T>) -> Self;
3+
fn get_differences(&self) -> Vec<T>;
4+
}
5+
6+
#[derive(Debug, Clone)]
7+
pub struct VectorComparer<T> {
8+
pub vec1: Vec<T>,
9+
pub vec2: Vec<T>,
10+
}
11+
12+
impl IVectorComparer<String> for VectorComparer<String> {
13+
/// Initialize a new VectorComparer for type `String`
14+
///
15+
/// # Example
16+
///
17+
/// ```rust
18+
/// let vector_comparer: VectorComparer<String> = IVectorComparer::<String>::new(vec![], vec![]);
19+
/// ```
20+
///
21+
/// # Returns
22+
///
23+
/// A `VectorComparer` that can be used to compare two `Vec` structs of type `String`
24+
fn new(vec1: Vec<String>, vec2: Vec<String>) -> VectorComparer<String> {
25+
VectorComparer::<String> { vec1, vec2 }
26+
}
27+
28+
/// Get the differences between the two given `Vec` structs of type `String`
29+
///
30+
/// # Example
31+
///
32+
/// ```rust
33+
/// let differences: Vec<String> = vector_comparer.get_differences();
34+
/// ```
35+
///
36+
/// # Returns
37+
///
38+
/// A `Vec` struct of type `String` that contains the differences between the two given `Vec` structs of type `String`
39+
fn get_differences(&self) -> Vec<String> {
40+
if self.vec1.is_empty() {
41+
return self.vec2.clone();
42+
} else if self.vec2.is_empty() {
43+
return self.vec1.clone();
44+
}
45+
46+
let mut diff = vec![];
47+
for f in &self.vec1 {
48+
let mut included = false;
49+
for d in &self.vec2 {
50+
if f.eq(d) {
51+
included = true;
52+
}
53+
}
54+
55+
if !included {
56+
diff.push(String::from(f));
57+
}
58+
}
59+
60+
for f in &self.vec2 {
61+
let mut included = false;
62+
for d in &self.vec1 {
63+
if f.eq(d) {
64+
included = true;
65+
}
66+
}
67+
68+
if !included {
69+
let n = String::from(f);
70+
if !diff.contains(&n) {
71+
diff.push(n);
72+
}
73+
}
74+
}
75+
76+
diff
77+
}
78+
}

src/vector_exporter.rs

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
use std::{fs::File, io::Write};
2+
3+
#[derive(Debug, Clone)]
4+
pub enum ExportType {
5+
Text,
6+
Csv,
7+
Json,
8+
}
9+
10+
pub enum ExportError {
11+
IoError(std::io::Error),
12+
JsonError(serde_json::Error),
13+
}
14+
15+
impl Default for ExportType {
16+
fn default() -> Self {
17+
ExportType::Text
18+
}
19+
}
20+
21+
pub trait IVectorExporter<T> {
22+
fn new(vec: Vec<T>, export_type: ExportType, export_type: &str) -> Self;
23+
24+
fn export(&self) -> Result<(), ExportError>;
25+
}
26+
27+
#[derive(Debug, Clone)]
28+
pub struct VectorExporter<T> {
29+
pub vec: Vec<T>,
30+
pub export_type: ExportType,
31+
pub export_path: String,
32+
}
33+
34+
impl IVectorExporter<String> for VectorExporter<String> {
35+
/// Initialize a new `VectorExporter` for type `String`
36+
///
37+
/// # Example
38+
///
39+
/// ```rust
40+
/// let vec_exporter: VectorExporter<String> = IVectorExporter::<String>::new(vec![], ExportType::default(), "/path/to/file");
41+
/// ```
42+
///
43+
/// # Returns
44+
///
45+
/// The `VectorExporter` struct for type `String`
46+
fn new(vec: Vec<String>, export_type: ExportType, export_path: &str) -> VectorExporter<String> {
47+
VectorExporter {
48+
vec,
49+
export_type,
50+
export_path: String::from(export_path),
51+
}
52+
}
53+
54+
/// Export the `Vec` of type `String` to a file
55+
///
56+
/// # Example
57+
///
58+
/// ```rust
59+
/// let res = vec_exporter.export();
60+
/// ```
61+
///
62+
/// # Returns
63+
///
64+
/// A `Result` that can either contain an `Ok` or an `Error` struct
65+
fn export(&self) -> Result<(), ExportError> {
66+
let file = File::create(&self.export_path);
67+
let mut file = match file {
68+
Ok(file) => file,
69+
Err(e) => return Err(ExportError::IoError(e)),
70+
};
71+
match self.export_type {
72+
ExportType::Text => {
73+
let mut data = String::new();
74+
for l in &self.vec {
75+
data.push_str(&format!("{}\n", l));
76+
}
77+
78+
match write!(file, "{}", data) {
79+
Ok(_) => Ok(()),
80+
Err(e) => Err(ExportError::IoError(e)),
81+
}
82+
}
83+
ExportType::Csv => {
84+
let mut data = String::new();
85+
for l in &self.vec {
86+
data.push_str(&format!("\"{}\"\n", l));
87+
}
88+
89+
match write!(file, "{}", data) {
90+
Ok(_) => Ok(()),
91+
Err(e) => Err(ExportError::IoError(e)),
92+
}
93+
}
94+
ExportType::Json => {
95+
let serialized = match serde_json::to_string(&self.vec) {
96+
Ok(d) => d,
97+
Err(e) => return Err(ExportError::JsonError(e)),
98+
};
99+
100+
match write!(file, "{}", serialized) {
101+
Ok(_) => Ok(()),
102+
Err(e) => Err(ExportError::IoError(e)),
103+
}
104+
}
105+
}
106+
}
107+
}

0 commit comments

Comments
 (0)