use serde::{Deserialize, Serialize};
pub use n5i::utils::{is_false, true_default};
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(untagged)]
pub enum StringLike {
String(String),
Int(i64),
Bool(bool),
Float(f64),
}
impl From<StringLike> for String {
fn from(s: StringLike) -> Self {
match s {
StringLike::String(s) => s,
StringLike::Int(i) => i.to_string(),
StringLike::Bool(b) => b.to_string(),
StringLike::Float(f) => f.to_string(),
}
}
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq)]
#[serde(untagged)]
pub enum StringOrNumber {
String(String),
Int(i64),
Float(f64),
}
#[must_use]
pub fn is_valid_name(s: &str) -> bool {
#[inline]
const fn alnum(c: u8) -> bool {
c.is_ascii_lowercase() || c.is_ascii_digit()
}
let b = s.as_bytes();
let n = b.len();
if n == 0 {
return false;
}
if !alnum(b[0]) {
return false;
}
let mut prev_dash = false;
for &c in &b[1..] {
if c == b'-' {
if prev_dash {
return false;
}
prev_dash = true;
} else if alnum(c) {
prev_dash = false;
} else {
return false;
}
}
!prev_dash
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_is_false() {
assert!(is_false(&false));
assert!(!is_false(&true));
}
#[test]
fn test_stringlike() {
assert_eq!(
Into::<String>::into(StringLike::String("Hello world".to_string())),
"Hello world".to_string()
);
assert_eq!(
Into::<String>::into(StringLike::Int(100)),
"100".to_string()
);
assert_eq!(
Into::<String>::into(StringLike::Bool(true)),
"true".to_string()
);
assert_eq!(
Into::<String>::into(StringLike::Float(1.23)),
"1.23".to_string()
);
}
#[test]
fn test_is_valid_name() {
assert!(is_valid_name("hello-world"));
assert!(is_valid_name("hello"));
assert!(is_valid_name("h"));
assert!(is_valid_name("hello123"));
assert!(!is_valid_name("-hello"));
assert!(!is_valid_name("hello-"));
assert!(!is_valid_name("hello_world"));
assert!(!is_valid_name("Hello"));
assert!(!is_valid_name(""));
assert!(!is_valid_name("hello--world"));
assert!(!is_valid_name("hello-wörld"));
}
}