use serde::de::{Deserializer, Visitor};
use std::fmt;
pub(crate) fn f32_or_str<'de, D>(deserializer: D) -> Result<f32, D::Error>
where
D: Deserializer<'de>,
{
deserializer.deserialize_any(AnyF32Visitor)
}
struct AnyF32Visitor;
impl<'de> Visitor<'de> for AnyF32Visitor {
type Value = f32;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("an i64 integer or string representation of i64")
}
fn visit_i32<E: serde::de::Error>(self, v: i32) -> Result<Self::Value, E> {
Ok(v as f32)
}
fn visit_i64<E: serde::de::Error>(self, v: i64) -> Result<Self::Value, E> {
Ok(v as f32)
}
fn visit_u32<E: serde::de::Error>(self, v: u32) -> Result<Self::Value, E> {
Ok(v as f32)
}
fn visit_u64<E: serde::de::Error>(self, v: u64) -> Result<Self::Value, E> {
Ok(v as f32)
}
fn visit_f32<E: serde::de::Error>(self, v: f32) -> Result<Self::Value, E> {
Ok(v as f32)
}
fn visit_f64<E: serde::de::Error>(self, v: f64) -> Result<Self::Value, E> {
Ok(v as f32)
}
fn visit_str<E: serde::de::Error>(self, v: &str) -> Result<Self::Value, E> {
match v.parse::<f32>() {
Ok(num) => Ok(num),
Err(_) => Err(E::custom(format!("not a valid float value: {}", v))),
}
}
}
pub(crate) fn join<T: AsRef<str>>(sep: &str, arr: &[T]) -> String {
if arr.is_empty() {
return String::from("");
}
let mut result = arr.get(0).unwrap().as_ref().to_string();
for s in &arr[1..] {
result.push_str(sep);
result.push_str(s.as_ref());
}
result
}
pub(crate) fn is_uuid(s: &str) -> bool {
if s.len() != 36 {
return false;
}
for buf in s.split('-') {
match buf.len() {
8 => {
if u64::from_str_radix(&buf, 16).is_err() {
return false;
}
}
4 => {
if u32::from_str_radix(&buf, 16).is_err() {
return false;
}
}
12 => {
if u64::from_str_radix(&buf[..6], 16).is_err()
|| u64::from_str_radix(&buf[6..], 16).is_err()
{
return false;
}
}
_ => return false,
}
}
true
}
#[cfg(test)]
mod test {
use super::{is_uuid, join};
#[test]
fn test_join() -> Result<(), ()> {
assert_eq!(&join(",", &Vec::<String>::new()), "", "empty array");
assert_eq!(&join(",", &vec!["ab"]), "ab", "1-list");
assert_eq!(&join(",", &vec!["ab", "cd"]), "ab,cd", "2-list");
assert_eq!(&join(",", &vec!["ab", "cd", "ef"]), "ab,cd,ef", "3-list");
assert_eq!(&join("", &vec!["ab", "cd"]), "abcd", "empty sep");
assert_eq!(&join("/", &vec!["", "home", "user"]), "/home/user", "mixed");
Ok(())
}
#[test]
fn test_uuid() {
for s in vec![
"00000000-0000-0000-0000-000000000000",
"abcdef00-1234-5678-9999-abcdefabcdef",
]
.iter()
{
assert_eq!(is_uuid(s), true, "expect good: {}", s);
}
for s in vec![
"",
"00000000",
"zzzzzzzz-0000-0000-0000-000000000000",
"000000000000000000000000000000000000",
]
.iter()
{
assert_ne!(is_uuid(s), true, "expect bad: {}", s);
}
}
}