yaxpeax_core/analyses/control_flow/
deserialize.rs1use analyses::control_flow::ControlFlowGraph;
2
3use yaxpeax_arch::Address;
4use std::hash::Hash;
5use std::fmt;
6
7use serde::de::{self, Deserialize, Deserializer, Visitor, SeqAccess, MapAccess};
8
9#[derive(Deserialize)]
10#[serde(field_identifier, rename_all = "lowercase")]
11enum Field { Entrypoint, Blocks, Graph }
12
13struct CFGVisitor<A> { _marker: std::marker::PhantomData<A> }
14
15impl<'de, A: Address + Hash> Visitor<'de> for CFGVisitor<A> {
16 type Value = ControlFlowGraph<A>;
17
18 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
19 formatter.write_str("struct ControlFlowGraph<A>")
20 }
21
22 fn visit_seq<V>(self, mut seq: V) -> Result<ControlFlowGraph<A>, V::Error>
23 where
24 V: SeqAccess<'de>,
25 {
26 let entrypoint = seq.next_element()?
27 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
28 let blocks = seq.next_element()?
29 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
30 let graph: crate::serialize::GraphDeserializer<A> = seq.next_element()?
31 .ok_or_else(|| de::Error::invalid_length(2, &self))?;
32 Ok(ControlFlowGraph {
33 entrypoint,
34 blocks,
35 graph: graph.into_inner(),
36 })
37 }
38
39 fn visit_map<V>(self, mut map: V) -> Result<ControlFlowGraph<A>, V::Error>
40 where
41 V: MapAccess<'de>,
42 {
43 let mut entrypoint = None;
44 let mut blocks = None;
45 let mut graph = None;
46 while let Some(key) = map.next_key()? {
47 match key {
48 Field::Entrypoint => {
49 if entrypoint.is_some() {
50 return Err(de::Error::duplicate_field("entrypoint"));
51 }
52 entrypoint = Some(map.next_value()?);
53 },
54 Field::Blocks => {
55 if blocks.is_some() {
56 return Err(de::Error::duplicate_field("blocks"));
57 }
58 blocks = Some(map.next_value()?);
59 },
60 Field::Graph => {
61 if graph.is_some() {
62 return Err(de::Error::duplicate_field("graph"));
63 }
64 graph = Some(map.next_value()?);
65 }
66 }
67 }
68 let entrypoint = entrypoint.ok_or_else(|| de::Error::missing_field("entrypoint"))?;
69 let blocks = blocks.ok_or_else(|| de::Error::missing_field("blocks"))?;
70 let graph: crate::serialize::GraphDeserializer<A> = graph.ok_or_else(|| de::Error::missing_field("graph"))?;
71 Ok(ControlFlowGraph {
72 entrypoint,
73 blocks,
74 graph: graph.into_inner(),
75 })
76 }
77}
78
79impl<'de, A: Address + Hash> Deserialize<'de> for ControlFlowGraph<A> {
80 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
81 where
82 D: Deserializer<'de>,
83 {
84
85 const FIELDS: &'static [&'static str] = &["entrypoint", "blocks", "graph"];
86 let visitor: CFGVisitor<A> = CFGVisitor { _marker: std::marker::PhantomData };
87 deserializer.deserialize_struct("CFG<A>", FIELDS, visitor)
88 }
89}