use regex::Regex;
use serde::de;
use serde::ser;
use std::fmt;
pub fn is_valid(s: &str) -> bool {
lazy_static! {
static ref RE: Regex =
Regex::new(r"^([A-Za-z][0-9A-Za-z_]*)?$").unwrap();
}
RE.is_match(s)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<String, D::Error>
where
D: de::Deserializer<'de>,
{
struct FieldVisitor;
impl<'de> de::Visitor<'de> for FieldVisitor {
type Value = String;
fn expecting(
&self,
formatter: &mut fmt::Formatter,
) -> fmt::Result {
formatter.write_str("an id string")
}
fn visit_str<E>(self, value: &str) -> Result<String, E>
where
E: de::Error,
{
if is_valid(value) {
Ok(value.to_string())
} else {
Err(de::Error::invalid_value(
de::Unexpected::Str(value),
&self,
))
}
}
}
deserializer.deserialize_string(FieldVisitor)
}
pub fn serialize<S>(s: &str, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
if is_valid(s) {
serializer.serialize_str(s)
} else {
Err(ser::Error::custom("regex does not match"))
}
}
#[cfg(test)]
mod tests {
#[test]
fn is_valid() {
assert!(super::is_valid("AnIdString"));
assert!(super::is_valid("AnotherIdString"));
assert!(super::is_valid("anId2"));
assert!(super::is_valid("anId2"));
assert!(super::is_valid("anId2_"));
assert!(super::is_valid("anId_2"));
assert!(super::is_valid("an_Id2"));
assert!(super::is_valid(""));
assert!(!super::is_valid(" "));
assert!(!super::is_valid("AnotherIdString "));
assert!(!super::is_valid(" AnotherIdString"));
assert!(!super::is_valid(" AnotherIdString "));
assert!(!super::is_valid("1AnotherIdString"));
assert!(!super::is_valid("_AnotherIdString"));
}
}