ts_error/
lib.rs

1//! # `ts-error`
2//!
3//! Traits for convenient error reporting, and error report/stack creation
4
5#![no_std]
6
7extern crate alloc;
8#[cfg(feature = "std")]
9extern crate std;
10
11pub mod diagnostic;
12mod logger;
13mod program_exit;
14mod report;
15
16use alloc::string::{String, ToString};
17
18#[cfg(feature = "log")]
19pub use logger::LogError;
20pub use program_exit::{ProgramReport, ReportProgramExit};
21pub use report::{IntoReport, Report};
22
23#[cfg(feature = "std")]
24pub use logger::StderrError;
25
26/// Normalize an error message.
27/// * Starts with lowercase character unless followed by an uppercase character.
28/// * Does not end with any punctuation.
29pub fn normalize_message<S: ToString>(message: S) -> String {
30    let message = message.to_string();
31    let message = message.trim();
32    let mut output = String::with_capacity(message.len());
33
34    let mut chars = message.chars();
35    let first_char = chars.next();
36    let second_char = chars.next();
37
38    // Handle acronyms
39    if let Some(first_char) = first_char
40        && let Some(second_char) = second_char
41        && first_char.is_uppercase()
42        && !second_char.is_uppercase()
43    {
44        output.push(first_char.to_ascii_lowercase());
45        output.push(second_char);
46    } else {
47        if let Some(first_char) = first_char {
48            output.push(first_char);
49        }
50        if let Some(second_char) = second_char {
51            output.push(second_char);
52        }
53    }
54
55    let mut chars = chars.rev().peekable();
56    // Skip trailing punctuation
57    while chars.next_if(char::is_ascii_punctuation).is_some() {}
58
59    output.push_str(&chars.rev().collect::<String>());
60
61    output.trim().to_string()
62}
63
64#[cfg(test)]
65mod test {
66    use crate::normalize_message;
67
68    #[test]
69    fn does_not_normalize_acronyms() {
70        let message = "JSON";
71        assert_eq!(message, normalize_message(message));
72
73        let message = "  JSON  ";
74        assert_eq!("JSON", normalize_message(message));
75    }
76
77    #[test]
78    fn normalizes_sentences() {
79        let message = "Whether";
80        assert_eq!("whether", normalize_message(message));
81
82        let message = "  Whether  ";
83        assert_eq!("whether", normalize_message(message));
84    }
85
86    #[test]
87    fn removes_punctuation() {
88        let message = "message.,;/";
89        assert_eq!("message", normalize_message(message));
90
91        let message = "  message .,;/  ";
92        assert_eq!("message", normalize_message(message));
93    }
94}