use std::collections::HashMap;
use std::fmt;
use std::marker::PhantomData;
use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};
#[derive(Debug, Clone, PartialEq)]
pub struct OrderedMap<V> {
entries: Vec<(String, V)>,
index: HashMap<String, usize>,
}
impl<V> OrderedMap<V> {
pub fn new() -> Self {
Self {
entries: Vec::new(),
index: HashMap::new(),
}
}
pub fn insert(&mut self, key: String, value: V) {
match self.index.get(&key) {
Some(&i) => self.entries[i].1 = value,
None => {
self.index.insert(key.clone(), self.entries.len());
self.entries.push((key, value));
}
}
}
pub fn get(&self, key: &str) -> Option<&V> {
self.index.get(key).map(|&i| &self.entries[i].1)
}
pub fn len(&self) -> usize {
self.entries.len()
}
pub fn is_empty(&self) -> bool {
self.entries.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&String, &V)> {
self.entries.iter().map(|(k, v)| (k, v))
}
}
impl<V> Default for OrderedMap<V> {
fn default() -> Self {
Self::new()
}
}
impl<V: Serialize> Serialize for OrderedMap<V> {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
let mut map = serializer.serialize_map(Some(self.entries.len()))?;
for (k, v) in &self.entries {
map.serialize_entry(k, v)?;
}
map.end()
}
}
impl<'de, V: Deserialize<'de>> Deserialize<'de> for OrderedMap<V> {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
struct OrderedMapVisitor<V>(PhantomData<V>);
impl<'de, V: Deserialize<'de>> Visitor<'de> for OrderedMapVisitor<V> {
type Value = OrderedMap<V>;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("a JSON object")
}
fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
let mut out = OrderedMap::new();
while let Some((k, v)) = map.next_entry::<String, V>()? {
out.insert(k, v);
}
Ok(out)
}
}
deserializer.deserialize_map(OrderedMapVisitor(PhantomData))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Percent1(pub i64);
impl Percent1 {
pub fn zero() -> Self {
Percent1(0)
}
pub fn from_ratio(numerator: usize, denominator: usize) -> Self {
if denominator == 0 {
return Percent1::zero();
}
let raw = (numerator as f64 / denominator as f64) * 1000.0;
Percent1(raw.round() as i64)
}
}
impl Serialize for Percent1 {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
if self.0 % 10 == 0 {
serializer.serialize_i64(self.0 / 10)
} else {
serializer.serialize_f64(self.0 as f64 / 10.0)
}
}
}
impl<'de> Deserialize<'de> for Percent1 {
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
let v = f64::deserialize(deserializer)?;
Ok(Percent1((v * 10.0).round() as i64))
}
}