use std::{
error::Error,
fmt::{Display, Formatter, Result as FmtResult},
};
pub const STICKER_DESCRIPTION_LENGTH_MAX: usize = 200;
pub const STICKER_DESCRIPTION_LENGTH_MIN: usize = 2;
pub const STICKER_NAME_LENGTH_MAX: usize = 30;
pub const STICKER_NAME_LENGTH_MIN: usize = 2;
pub const STICKER_TAGS_LENGTH_MAX: usize = 200;
pub const STICKER_TAGS_LENGTH_MIN: usize = 2;
#[derive(Debug)]
pub struct StickerValidationError {
kind: StickerValidationErrorType,
}
impl StickerValidationError {
#[must_use = "retrieving the type has no effect if left unused"]
pub const fn kind(&self) -> &StickerValidationErrorType {
&self.kind
}
#[allow(clippy::unused_self)]
#[must_use = "consuming the error and retrieving the source has no effect if left unused"]
pub fn into_source(self) -> Option<Box<dyn Error + Send + Sync>> {
None
}
#[must_use = "consuming the error into its parts has no effect if left unused"]
pub fn into_parts(
self,
) -> (
StickerValidationErrorType,
Option<Box<dyn Error + Send + Sync>>,
) {
(self.kind, None)
}
}
impl Display for StickerValidationError {
fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
match self.kind {
StickerValidationErrorType::DescriptionInvalid => {
f.write_str("sticker's description is invalid")
}
StickerValidationErrorType::NameInvalid => f.write_str("sticker's name is invalid"),
StickerValidationErrorType::TagsInvalid => f.write_str("sticker's tags are invalid"),
}
}
}
impl Error for StickerValidationError {}
#[derive(Debug)]
pub enum StickerValidationErrorType {
DescriptionInvalid,
NameInvalid,
TagsInvalid,
}
pub fn description(value: impl AsRef<str>) -> Result<(), StickerValidationError> {
let len = value.as_ref().chars().count();
if (STICKER_DESCRIPTION_LENGTH_MIN..=STICKER_DESCRIPTION_LENGTH_MAX).contains(&len) {
Ok(())
} else {
Err(StickerValidationError {
kind: StickerValidationErrorType::DescriptionInvalid,
})
}
}
pub fn name(value: impl AsRef<str>) -> Result<(), StickerValidationError> {
let len = value.as_ref().chars().count();
if (STICKER_NAME_LENGTH_MIN..=STICKER_NAME_LENGTH_MAX).contains(&len) {
Ok(())
} else {
Err(StickerValidationError {
kind: StickerValidationErrorType::NameInvalid,
})
}
}
pub fn tags(value: impl AsRef<str>) -> Result<(), StickerValidationError> {
let len = value.as_ref().chars().count();
if (STICKER_TAGS_LENGTH_MIN..=STICKER_TAGS_LENGTH_MAX).contains(&len) {
Ok(())
} else {
Err(StickerValidationError {
kind: StickerValidationErrorType::TagsInvalid,
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn description_length() {
assert!(description("aa").is_ok());
assert!(description("a".repeat(200)).is_ok());
assert!(description("a").is_err());
assert!(description("a".repeat(201)).is_err());
}
#[test]
fn name_length() {
assert!(name("aa").is_ok());
assert!(name("a".repeat(30)).is_ok());
assert!(name("a").is_err());
assert!(name("a".repeat(31)).is_err());
}
#[test]
fn tags_length() {
assert!(tags("aa").is_ok());
assert!(tags("a".repeat(200)).is_ok());
assert!(tags("a").is_err());
assert!(tags("a".repeat(201)).is_err());
}
}