yaxpeax_core/analyses/control_flow/
deserialize.rs

1use 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}