use std::{error::Error, ops::Range}; use unicode_segmentation::UnicodeSegmentation; pub(crate) fn validate_optional_length( opt: &Option, len_range: Range, err: E, ) -> Result, E> { if let Some(opt) = opt { let opt = opt.trim(); let len = opt.graphemes(true).size_hint().1.unwrap(); if !len_range.contains(&len) { Err(err) } else { Ok(Some(opt.to_string())) } } else { Ok(None) } } /// Serde deserialization decorator to map empty Strings to None pub(crate) fn empty_string_as_none<'de, D, T>(de: D) -> Result, D::Error> where D: serde::Deserializer<'de>, T: std::str::FromStr, T::Err: std::fmt::Display, { let opt = as serde::Deserialize>::deserialize(de)?; match opt.as_deref() { None | Some("") => Ok(None), Some(s) => std::str::FromStr::from_str(s) .map_err(serde::de::Error::custom) .map(Some), } }