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
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde_json::{json, Map};

use crate::event::{EventType, Keyframe, TraceEvent};
use crate::VERSION;

#[derive(Debug)]
pub struct Metadata {
    pub address: String,
}

impl Default for Metadata {
    fn default() -> Self {
        Metadata {
            address: "".to_string(),
        }
    }
}

#[derive(Debug)]
pub struct TracePoint {
    pub timestamp: u64,
    pub event: TraceEvent,
    pub metadata: Metadata,
}

/// assign json
/// ```
/// use serde_json::Map;
///
/// let mut map = Map::new();
/// let value1 = 1;
/// let value2 = 2;
/// assign!(map, value1, value2); // { "value1": 1, "value2": 2 }
/// ```
macro_rules! assign {
    ($map:expr) => {};
    ($map:expr, $($key:ident),*) => {
      $(
         $map.insert(String::from(stringify!($key)), json!($key));
      )*
    };
}

impl Serialize for TracePoint {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let event_name = &self.event.event_name;

        let mut state = serializer.serialize_struct("TracePoint", 2)?;
        state.serialize_field("timestamp", &self.timestamp)?;
        state.serialize_field("event_name", event_name)?;

        let mut tag = match &self.event.tag {
            Some(json) => json.clone(),
            _ => json!({}),
        };

        let map = tag.as_object_mut().unwrap();

        // fill tag and event_type
        match &self.event.event_type {
            EventType::Propose {
                block_height,
                round_id,
                proposer,
                hash,
            } => {
                state.serialize_field("event_type", "propose")?;
                assign!(map, block_height, round_id, proposer, hash);
            }

            EventType::Vote {
                block_height,
                round_id,
                voter,
                hash,
            } => {
                state.serialize_field("event_type", "vote")?;
                assign!(map, block_height, round_id, voter, hash);
            }

            EventType::Keyframe { frame_info } => {
                state.serialize_field("event_type", "keyframe")?;

                match frame_info {
                    Keyframe::NewBlock { block_height } => {
                        assign!(map, block_height);
                    }
                    Keyframe::NewRound { round_id, block_height } => {
                        assign!(map, round_id, block_height);
                    }
                    Keyframe::NewStep {
                        step_name,
                        round_id,
                        block_height,
                    } => {
                        assign!(map, step_name, round_id, block_height);
                    }
                }
            }
            EventType::Error => {
                state.serialize_field("event_type", "error")?;
            }
            _ => {
                state.serialize_field("event_type", "custom")?;
            }
        }

        state.serialize_field("tag", &tag)?;
        let mut metadata = Map::new();
        let address = &self.metadata.address.clone();
        let v = VERSION;
        assign!(metadata, address, v);
        state.serialize_field("metadata", &metadata)?;
        state.end()
    }
}