Skip to content

Instantly share code, notes, and snippets.

@matdexir

matdexir/main.rs Secret

Created April 25, 2024 14:58
Show Gist options
  • Save matdexir/8b0285a63ec744f55d76131de643149a to your computer and use it in GitHub Desktop.
Save matdexir/8b0285a63ec744f55d76131de643149a to your computer and use it in GitHub Desktop.
use serde::de::{self, Deserialize, Visitor};
use std::fmt;
pub struct Quantity(u64);
impl fmt::Display for Quantity {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.0)
}
}
impl From<u64> for Quantity {
fn from(value: u64) -> Self {
Quantity(value)
}
}
impl From<Quantity> for u64 {
fn from(value: Quantity) -> u64 {
value.0
}
}
struct QuantityVisitor;
impl<'de> Visitor<'de> for QuantityVisitor {
type Value = Quantity;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("str of form `5kB` or `10MiB`")
}
fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
if let Some((number, unit)) = split_unit(v) {
let parsed_value: u64 = number.parse().expect("Failed to parse number");
let true_value = match_true_value(parsed_value, unit.as_str());
Ok(Quantity(true_value as u64))
} else {
Err(E::custom(format!("Unable to parse the true quantity")))
}
}
}
impl<'de> Deserialize<'de> for Quantity {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: de::Deserializer<'de>,
{
deserializer.deserialize_str(QuantityVisitor)
}
}
fn match_true_value(value: u64, unit: &str) -> u64 {
match unit {
"kB" => value * 1000,
"KiB" => value * 1024,
"mB" => value * 1000 * 1000,
_ => value,
}
}
fn split_unit(text: &str) -> Option<(String, String)> {
let chars = text.chars();
let mut split_idx = None;
for (i, c) in chars.enumerate() {
if c.is_alphabetic() {
split_idx = Some(i);
break;
}
}
if let Some(i) = split_idx {
let number = text[..i].to_string();
let unit = text[i..].to_string();
Some((number, unit))
} else {
None
}
}
fn main() {
println!("Hello, world!");
const VALUE: &str = "\"10KiB\"";
let deserialized: Quantity = serde_json::from_str(&VALUE).unwrap();
// let deser: i32 = serde_json::from_str("5").unwrap();
println!("{}", deserialized);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment