near_facsimile/
lib.rs

1/*
2Copyright 2022 Marek Suchánek <msuchane@redhat.com>
3
4Licensed under the Apache License, Version 2.0 (the "License");
5you may not use this file except in compliance with the License.
6You may obtain a copy of the License at
7
8    http://www.apache.org/licenses/LICENSE-2.0
9
10Unless required by applicable law or agreed to in writing, software
11distributed under the License is distributed on an "AS IS" BASIS,
12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13See the License for the specific language governing permissions and
14limitations under the License.
15*/
16
17// Enable additional clippy lints by default.
18#![warn(
19    clippy::pedantic,
20    clippy::unwrap_used,
21    clippy::clone_on_ref_ptr,
22    clippy::todo
23)]
24// Forbid unsafe code in this program.
25#![forbid(unsafe_code)]
26
27use std::path::PathBuf;
28
29use color_eyre::{eyre::bail, Result};
30use permutator::Combination;
31
32pub mod cli;
33mod comparison;
34mod load_files;
35mod logging;
36mod percentage;
37mod serialize;
38
39use cli::Cli;
40use comparison::{comparisons, Comparison};
41use load_files::files;
42pub use logging::init_log_and_errors;
43use serialize::serialize;
44
45/// Represents a loaded text file, with its path and content.
46#[derive(Debug)]
47pub struct File {
48    pub path: PathBuf,
49    pub content: String,
50}
51
52pub fn run(options: &Cli) -> Result<()> {
53    // Check that the similarity threshold is a valid percentage between 0% and 100%.
54    // The value is stored as a decimal between 0 and 1, but it's exposed to the user
55    // as a value between 0 and 100.
56    if options.threshold < 0.0 || options.threshold > 1.0 {
57        bail!("The similarity threshold must be between 0.0 and 100.0.")
58    }
59
60    // Load all matching files from the directory.
61    let files = files(options)?;
62
63    // The comparison needs at least two files.
64    if files.len() < 2 {
65        bail!("Too few files that match the settings to compare in this directory.");
66    }
67
68    // Combinations by 2 pair each file with each file, so that no comparison
69    // occurs more than once.
70    let combinations = files.combination(2).map(|v| (v[0], v[1]));
71
72    let comparisons = comparisons(combinations, options);
73
74    // Only serialize if at least one serialization options is active.
75    if options.csv.is_some() || options.json.is_some() {
76        serialize(comparisons, options)?;
77    }
78
79    Ok(())
80}