devscout_rs/graph/
ordered.rs1use std::collections::HashMap;
2use std::fmt;
3use std::marker::PhantomData;
4
5use serde::de::{MapAccess, Visitor};
6use serde::ser::SerializeMap;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8
9#[derive(Debug, Clone, PartialEq)]
21pub struct OrderedMap<V> {
23 entries: Vec<(String, V)>,
24 index: HashMap<String, usize>,
25}
26
27impl<V> OrderedMap<V> {
28 pub fn new() -> Self {
30 Self {
31 entries: Vec::new(),
32 index: HashMap::new(),
33 }
34 }
35
36 pub fn insert(&mut self, key: String, value: V) {
40 match self.index.get(&key) {
41 Some(&i) => self.entries[i].1 = value,
42 None => {
43 self.index.insert(key.clone(), self.entries.len());
44 self.entries.push((key, value));
45 }
46 }
47 }
48
49 pub fn get(&self, key: &str) -> Option<&V> {
51 self.index.get(key).map(|&i| &self.entries[i].1)
52 }
53
54 pub fn len(&self) -> usize {
56 self.entries.len()
57 }
58
59 pub fn is_empty(&self) -> bool {
61 self.entries.is_empty()
62 }
63
64 pub fn iter(&self) -> impl Iterator<Item = (&String, &V)> {
66 self.entries.iter().map(|(k, v)| (k, v))
67 }
68}
69
70impl<V> Default for OrderedMap<V> {
71 fn default() -> Self {
72 Self::new()
73 }
74}
75
76impl<V: Serialize> Serialize for OrderedMap<V> {
77 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
78 let mut map = serializer.serialize_map(Some(self.entries.len()))?;
79 for (k, v) in &self.entries {
80 map.serialize_entry(k, v)?;
81 }
82 map.end()
83 }
84}
85
86impl<'de, V: Deserialize<'de>> Deserialize<'de> for OrderedMap<V> {
87 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
88 struct OrderedMapVisitor<V>(PhantomData<V>);
89
90 impl<'de, V: Deserialize<'de>> Visitor<'de> for OrderedMapVisitor<V> {
91 type Value = OrderedMap<V>;
92
93 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
94 f.write_str("a JSON object")
95 }
96
97 fn visit_map<A: MapAccess<'de>>(self, mut map: A) -> Result<Self::Value, A::Error> {
98 let mut out = OrderedMap::new();
99 while let Some((k, v)) = map.next_entry::<String, V>()? {
100 out.insert(k, v);
101 }
102 Ok(out)
103 }
104 }
105
106 deserializer.deserialize_map(OrderedMapVisitor(PhantomData))
107 }
108}
109
110#[derive(Debug, Clone, Copy, PartialEq, Eq)]
117pub struct Percent1(pub i64);
119
120impl Percent1 {
121 pub fn zero() -> Self {
123 Percent1(0)
124 }
125
126 pub fn from_ratio(numerator: usize, denominator: usize) -> Self {
130 if denominator == 0 {
131 return Percent1::zero();
132 }
133 let raw = (numerator as f64 / denominator as f64) * 1000.0;
134 Percent1(raw.round() as i64)
135 }
136}
137
138impl Serialize for Percent1 {
139 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
140 if self.0 % 10 == 0 {
141 serializer.serialize_i64(self.0 / 10)
142 } else {
143 serializer.serialize_f64(self.0 as f64 / 10.0)
144 }
145 }
146}
147
148impl<'de> Deserialize<'de> for Percent1 {
149 fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
150 let v = f64::deserialize(deserializer)?;
151 Ok(Percent1((v * 10.0).round() as i64))
152 }
153}