use std::time::{SystemTime, UNIX_EPOCH};
use serde::de::DeserializeOwned;
use serde_json::Value;
pub enum JsonParseError {
ParseError(String),
EmptyInput,
InvalidFormat,
}
pub fn parse_json_detailed<T>(json: impl AsRef<str>) -> Result<T, JsonParseError>
where
T: DeserializeOwned,
{
let json = json.as_ref();
if json.trim().is_empty() {
return Err(JsonParseError::EmptyInput);
}
let value: Value = serde_json::from_str(json).map_err(|e| {
tracing::error!("Invalid JSON format: {}", e);
JsonParseError::InvalidFormat
})?;
serde_json::from_value(value).map_err(|e| {
tracing::error!(
"Error parsing JSON into specific type: {}, Input: {}",
e,
if json.len() > 100 {
format!("{}...(truncated)", &json[..100])
} else {
json.to_string()
}
);
JsonParseError::ParseError(e.to_string())
})
}
pub fn generate_between(min: i8, max: i8) -> i8 {
let range = (max - min) as u32;
let timestamp = SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.subsec_nanos();
min + (timestamp % range) as i8
}
pub fn parse_json_optional<T>(json: impl AsRef<str>) -> Option<T>
where
T: DeserializeOwned,
{
match parse_json_detailed(json) {
Ok(parsed) => Some(parsed),
Err(err) => {
match err {
JsonParseError::EmptyInput => {
tracing::debug!("Empty JSON input received");
}
JsonParseError::InvalidFormat => {
tracing::warn!("Invalid JSON format");
}
JsonParseError::ParseError(e) => {
tracing::error!("JSON parse error: {}", e);
}
}
None
}
}
}