1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
use std::collections::{HashMap, HashSet};
use std::fmt;
use itertools::Itertools;
use serde::de::{self, Deserialize, Visitor};
use serde_json::Value as Json;
use super::super::{ItemSockets, SocketGroup};
use super::util::deserialize;
const EXPECTING_MSG: &str = "map with sockets data";
impl<'de> Deserialize<'de> for ItemSockets {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where D: de::Deserializer<'de>
{
deserializer.deserialize_seq(ItemSocketsVisitor)
}
}
struct ItemSocketsVisitor;
impl<'de> Visitor<'de> for ItemSocketsVisitor {
type Value = ItemSockets;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "{}", EXPECTING_MSG)
}
fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
where V: de::SeqAccess<'de>
{
if let Some(0) = seq.size_hint() {
return Ok(ItemSockets::default());
}
let mut abyssal_count = 0;
let mut regular_groups = HashMap::new();
let mut indices = HashSet::new();
while let Some(socket) = seq.next_element::<HashMap<String, Json>>()? {
let color = socket.get("sColour").and_then(|c| c.as_str())
.ok_or_else(|| de::Error::missing_field("sColour"))?;
if color == "A" {
abyssal_count += 1;
continue;
}
let group = socket.get("group").and_then(|g| g.as_u64())
.ok_or_else(|| de::Error::missing_field("group"))?;
let regular_color = deserialize(color)?;
regular_groups.entry(group).or_insert_with(Vec::new)
.push(regular_color);
indices.insert(group);
}
let expected_indices = (0u64..indices.len() as u64).collect_vec();
let actual_indices = indices.into_iter().sorted();
if actual_indices != expected_indices {
return Err(de::Error::custom(format!(
"socket group indices not in a contiguous range: expected {:?}, got {:?}",
expected_indices, actual_indices)));
}
let regular_groups = regular_groups.into_iter()
.sorted_by_key(|&(i, _)| i).into_iter()
.map(|(i, g)| SocketGroup{id: i as u8, colors: g})
.collect();
Ok(ItemSockets{abyssal_count, regular_groups})
}
}