ecformat 0.1.1

command line tool to keep files correct in respect of your EditorConfig
Documentation
// SPDX-FileCopyrightText: Contributors to ecformat project <https://codeberg.org/BaumiCoder/ecformat>
//
// SPDX-License-Identifier: BlueOak-1.0.0

//! Error types related to EditorConfig.

use std::{collections::HashMap, path::PathBuf};

use ec4rs::property;
use itertools::Itertools;
use snafu::Snafu;

/// Type of check error (i.e., which EditorConfig property is violated).
#[derive(Debug, Snafu)]
#[snafu(visibility(pub))]
pub enum CheckErrorType {
    /// The charset in a file does not respect the EditorConfig property `charset`.
    #[snafu(display("charset {actual_charset} instead of {expected_charset}"))]
    CharsetError {
        /// The name of the charset which was determined by inspecting the files content.
        actual_charset: String,
        /// The charset specified for the file with EditorConfig.
        expected_charset: property::Charset,
    },
    /// The end of line characters does not respect the EditorConfig property `end_of_line`.
    #[snafu(display(
        "{} instead of only using end of line '{expected_end_of_line}'",
        wrong_end_of_lines
            .iter()
            .map(|(end_of_line, count)| format!("end of line '{end_of_line}' occurres {count} time(s)"))
            .join(" and ")
    ))]
    EndOfLineError {
        /// The end of line character(s) specified for the file with EditorConfig.
        expected_end_of_line: property::EndOfLine,
        /// The wrong end of line characters and how often they occurred in the file.
        wrong_end_of_lines: HashMap<property::EndOfLine, usize>,
    },
}

/// A check on a specific file found a violation of a EditorConfig property.
#[derive(Debug, Snafu)]
#[snafu(display("{}: {error_type}", path.display()), visibility(pub))]
pub struct CheckError {
    path: PathBuf,
    error_type: CheckErrorType,
}

impl CheckError {
    /// Path to the file with the violation of a EditorConfig property.
    pub fn path(&self) -> &PathBuf {
        &self.path
    }
    pub fn error_type(&self) -> &CheckErrorType {
        &self.error_type
    }
}

/// List of [`CheckError`] instances which occurred in a [`crate::check`] call.
/// Itself is display as a message about the number of check errors,
/// which was logged as errors when they occurred.
///
/// You can consider the single errors via [`CheckErrorList::errors`]
#[derive(Debug, Snafu)]
#[snafu(display("Check failed with {} errors", errors.len()), visibility(pub))]
pub struct CheckErrorList {
    errors: Vec<CheckError>,
}

impl CheckErrorList {
    /// Returns the list of the errors occurred during the check.
    pub fn errors(&self) -> &Vec<CheckError> {
        &self.errors
    }
}

impl<'a> IntoIterator for &'a CheckErrorList {
    type Item = &'a CheckError;

    type IntoIter = std::slice::Iter<'a, CheckError>;

    fn into_iter(self) -> Self::IntoIter {
        self.errors.iter()
    }
}