1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
//! SaRcAsM tExT creation and validation library.
//!
//! This library provides utilities for creating and validating the capitalization style known as
//! SaRcAsM tExT. It is the library behind the command line utility `sarcasm` which provides a
//! convenient interface for day-to-day use, including automatic copying to the clipboard.
//!
//! All steps have been taken to make the library production ready. It has full logging via the
//! `log` crate and code should be panic free unless otherwise noted. If a panic is found in a
//! non-labeled function, this is a bug.
//!
//! Feature requests, pull requests, and issues are all welcome.
//!
//! # Example
//!
//! For more details, see [`encode_sarcasm`] and [`is_sarcasm`].
//!
//! ```rust,edition2018
//! use sarcasm_utils::{StartingCase, is_sarcasm, IsSarcasm};
//! use sarcasm_utils::encode_sarcasm;
//!
//! // Encoding SaRcAsM
//! let encoded: String = encode_sarcasm("Hello!", StartingCase::Uppercase);
//! assert_eq!(encoded, "HeLlO!");
//!
//! // Decoding SaRcAsM
//! let decoded: IsSarcasm = is_sarcasm(&encoded);
//! assert_eq!(decoded, IsSarcasm::Yes(StartingCase::Uppercase));
//!
//! // Matching on the type of SaRcAsM
//! match decoded {
//!     IsSarcasm::Yes(StartingCase::Uppercase) => println!("UpPeRcAsE sArCaSm!"),
//!     IsSarcasm::Yes(StartingCase::Lowercase) => println!("lOwErCaSe SaRcAsM!"),
//!     IsSarcasm::No => println!("No sarcasm here!"),
//!     IsSarcasm::TooShort => println!("Can't tell if there's sarcasm!"),
//! }
//! ```
//!
//! # Why?
//!
//! Because.
//!
//! # Is this a joke?
//!
//! No.
//!
//! # Really?
//!
//! Okay, yes the purpose is silly, but this was an exercise in writing a library in rust
//! that is designed to be robust yet easy to use. Also, it does provide some (minimal) use for
//! someone who wants to do this kind of thing. I will do my best to maintain and attend to this
//! library, as well as expand it with new "useful" features in the future.
//!
//! In short: maybe?
//!
//! # Be Nice
//!
//! Don't use this library to be jerks to people. It ruins the fun.

#![deny(nonstandard_style)]
#![deny(future_incompatible)]
#![deny(rust_2018_idioms)]
#![deny(unsafe_code)]
#![warn(missing_docs)]
#![warn(unused)]

mod decode;
mod encode;

pub use decode::*;
pub use encode::*;
use log::{debug, error, trace};

/// The case of the first letter in SaRcAsM tExT.
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum StartingCase {
    /// First letter is lOwErCaSe
    Lowercase,
    /// First letter is UpPeRcAsE
    Uppercase,
}

#[doc(hidden)]
impl From<char> for StartingCase {
    fn from(c: char) -> Self {
        trace!("Analyzing case of leading char {}", c);
        if c.is_lowercase() {
            debug!("Leading character {} is lowercase", c);
            StartingCase::Lowercase
        } else if c.is_uppercase() {
            debug!("Leading character {} is uppercase", c);
            StartingCase::Uppercase
        } else {
            let msg = format!("Invalid char {} provided to From<char> for StartingCase", c);
            error!("{}", msg);
            StartingCase::Uppercase
        }
    }
}

#[cfg(test)]
mod tests {
    use crate::{IsSarcasm, StartingCase};

    #[test]
    fn encode() {
        assert_eq!(crate::encode_sarcasm("hello!", StartingCase::Uppercase), "HeLlO!");
        assert_eq!(crate::encode_sarcasm("hello!", StartingCase::Lowercase), "hElLo!");
    }

    #[test]
    fn multi_word_encode() {
        assert_eq!(
            crate::encode_sarcasm("Hello World!", StartingCase::Uppercase),
            "HeLlO WoRlD!"
        );
        assert_eq!(
            crate::encode_sarcasm("Hello World!", StartingCase::Lowercase),
            "hElLo wOrLd!"
        );
    }

    #[test]
    fn encode_nothing() {
        assert_eq!(crate::encode_sarcasm("", StartingCase::Uppercase), "");
        assert_eq!(crate::encode_sarcasm("", StartingCase::Lowercase), "");
    }

    #[test]
    fn decode() {
        assert_eq!(crate::is_sarcasm("HeLlO!"), IsSarcasm::Yes(StartingCase::Uppercase));
        assert_eq!(crate::is_sarcasm("hElLo!"), IsSarcasm::Yes(StartingCase::Lowercase));
    }

    #[test]
    fn multi_word_decode() {
        assert_eq!(
            crate::is_sarcasm("HeLlO! hElLo!"),
            IsSarcasm::Yes(StartingCase::Uppercase)
        );
        assert_eq!(
            crate::is_sarcasm("hElLo! HeLlO!"),
            IsSarcasm::Yes(StartingCase::Lowercase)
        );

        assert_eq!(
            crate::is_sarcasm("HeLlO! HeLlO!"),
            IsSarcasm::Yes(StartingCase::Uppercase)
        );
        assert_eq!(
            crate::is_sarcasm("hElLo! hElLo!"),
            IsSarcasm::Yes(StartingCase::Lowercase)
        );
    }

    #[test]
    fn empty_decode() {
        assert_eq!(crate::is_sarcasm(""), IsSarcasm::TooShort);
    }

    #[test]
    fn negatives_decode() {
        assert_eq!(crate::is_sarcasm("Not Sarcasm"), IsSarcasm::No);
        assert_eq!(crate::is_sarcasm("NoT SaRcASM"), IsSarcasm::No);
    }

    #[test]
    fn first_character_decode() {
        assert_eq!(crate::is_sarcasm("heLlO!"), IsSarcasm::No);
        assert_eq!(crate::is_sarcasm("HElLo!"), IsSarcasm::No);
    }
}