use prost::Message;
use dyn_encoding::{WireTypeId, WireValue};
pub const DT_FETCH_REQ_CODE: u8 = 80;
pub const DT_FETCH_RESP_CODE: u8 = 81;
pub const DT_UPDATE_REQ_CODE: u8 = 82;
pub const DT_UPDATE_RESP_CODE: u8 = 83;
pub const DATA_TYPE_COUNTER: i32 = 1;
pub const DATA_TYPE_SET: i32 = 2;
pub const DATA_TYPE_MAP: i32 = 3;
pub const DATA_TYPE_HLL: i32 = 4;
pub const DATA_TYPE_GSET: i32 = 5;
#[derive(Clone, Eq, PartialEq, Message)]
pub struct CounterOp {
#[prost(sint64, optional, tag = "1")]
pub increment: Option<i64>,
}
impl WireValue for CounterOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.CounterOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct SetOp {
#[prost(bytes = "vec", repeated, tag = "1")]
pub adds: Vec<Vec<u8>>,
#[prost(bytes = "vec", repeated, tag = "2")]
pub removes: Vec<Vec<u8>>,
}
impl WireValue for SetOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.SetOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct HllOp {
#[prost(bytes = "vec", repeated, tag = "1")]
pub add_value: Vec<Vec<u8>>,
}
impl WireValue for HllOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.HllOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct HllValue {
#[prost(uint64, tag = "1")]
pub cardinality: u64,
}
impl WireValue for HllValue {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.HllValue")
}
}
pub const MAP_FIELD_TYPE_COUNTER: i32 = 1;
pub const MAP_FIELD_TYPE_SET: i32 = 2;
pub const MAP_FIELD_TYPE_REGISTER: i32 = 3;
pub const MAP_FIELD_TYPE_FLAG: i32 = 4;
pub const MAP_FIELD_TYPE_MAP: i32 = 5;
#[derive(Clone, Eq, PartialEq, Message)]
pub struct MapField {
#[prost(bytes = "vec", tag = "1")]
pub name: Vec<u8>,
#[prost(int32, tag = "2")]
pub field_type: i32,
}
impl WireValue for MapField {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.MapField")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct RegisterOp {
#[prost(bytes = "vec", tag = "1")]
pub value: Vec<u8>,
#[prost(uint64, optional, tag = "2")]
pub ts_micros: Option<u64>,
}
impl WireValue for RegisterOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.RegisterOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct FlagOp {
#[prost(bool, tag = "1")]
pub enable: bool,
}
impl WireValue for FlagOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.FlagOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct ScalarOp {
#[prost(message, optional, tag = "1")]
pub counter_op: Option<CounterOp>,
#[prost(message, optional, tag = "2")]
pub set_op: Option<SetOp>,
#[prost(message, optional, tag = "3")]
pub register_op: Option<RegisterOp>,
#[prost(message, optional, tag = "4")]
pub flag_op: Option<FlagOp>,
#[prost(message, optional, boxed, tag = "5")]
pub map_op: Option<Box<MapOp>>,
}
impl WireValue for ScalarOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.ScalarOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct MapUpdate {
#[prost(message, optional, tag = "1")]
pub field: Option<MapField>,
#[prost(message, optional, tag = "2")]
pub op: Option<ScalarOp>,
}
impl WireValue for MapUpdate {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.MapUpdate")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct MapOp {
#[prost(message, repeated, tag = "1")]
pub updates: Vec<MapUpdate>,
#[prost(message, repeated, tag = "2")]
pub removes: Vec<MapField>,
}
impl WireValue for MapOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.MapOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct ScalarValue {
#[prost(sint64, optional, tag = "1")]
pub counter_value: Option<i64>,
#[prost(bytes = "vec", repeated, tag = "2")]
pub set_value: Vec<Vec<u8>>,
#[prost(bytes = "vec", optional, tag = "3")]
pub register_value: Option<Vec<u8>>,
#[prost(bool, optional, tag = "4")]
pub flag_value: Option<bool>,
#[prost(message, optional, boxed, tag = "5")]
pub map_value: Option<Box<MapValue>>,
}
impl WireValue for ScalarValue {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.ScalarValue")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct MapEntry {
#[prost(message, optional, tag = "1")]
pub field: Option<MapField>,
#[prost(message, optional, tag = "2")]
pub value: Option<ScalarValue>,
}
impl WireValue for MapEntry {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.MapEntry")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct MapValue {
#[prost(message, repeated, tag = "1")]
pub entries: Vec<MapEntry>,
}
impl WireValue for MapValue {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.MapValue")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct GSetOp {
#[prost(bytes = "vec", repeated, tag = "1")]
pub adds: Vec<Vec<u8>>,
}
impl WireValue for GSetOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.GSetOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct DtOp {
#[prost(message, optional, tag = "1")]
pub counter_op: Option<CounterOp>,
#[prost(message, optional, tag = "2")]
pub set_op: Option<SetOp>,
#[prost(message, optional, boxed, tag = "3")]
pub map_op: Option<Box<MapOp>>,
#[prost(message, optional, tag = "4")]
pub hll_op: Option<HllOp>,
#[prost(message, optional, tag = "5")]
pub gset_op: Option<GSetOp>,
}
impl WireValue for DtOp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.DtOp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct DtValue {
#[prost(sint64, optional, tag = "1")]
pub counter_value: Option<i64>,
#[prost(bytes = "vec", repeated, tag = "2")]
pub set_value: Vec<Vec<u8>>,
#[prost(message, optional, boxed, tag = "3")]
pub map_value: Option<Box<MapValue>>,
#[prost(uint64, optional, tag = "4")]
pub hll_value: Option<u64>,
#[prost(bytes = "vec", repeated, tag = "5")]
pub gset_value: Vec<Vec<u8>>,
}
impl WireValue for DtValue {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.DtValue")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct DtFetchReq {
#[prost(bytes = "vec", tag = "1")]
pub bucket: Vec<u8>,
#[prost(bytes = "vec", tag = "2")]
pub key: Vec<u8>,
#[prost(bytes = "vec", tag = "3")]
pub r#type: Vec<u8>,
#[prost(uint32, optional, tag = "4")]
pub r: Option<u32>,
#[prost(uint32, optional, tag = "5")]
pub pr: Option<u32>,
#[prost(bool, optional, tag = "6")]
pub basic_quorum: Option<bool>,
#[prost(bool, optional, tag = "7")]
pub notfound_ok: Option<bool>,
#[prost(uint32, optional, tag = "8")]
pub timeout: Option<u32>,
#[prost(bool, optional, tag = "9")]
pub sloppy_quorum: Option<bool>,
#[prost(uint32, optional, tag = "10")]
pub n_val: Option<u32>,
#[prost(bool, optional, tag = "11")]
pub include_context: Option<bool>,
}
impl WireValue for DtFetchReq {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.DtFetchReq")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct DtFetchResp {
#[prost(bytes = "vec", optional, tag = "1")]
pub context: Option<Vec<u8>>,
#[prost(int32, tag = "2")]
pub r#type: i32,
#[prost(message, optional, tag = "3")]
pub value: Option<DtValue>,
}
impl WireValue for DtFetchResp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.DtFetchResp")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct DtUpdateReq {
#[prost(bytes = "vec", tag = "1")]
pub bucket: Vec<u8>,
#[prost(bytes = "vec", optional, tag = "2")]
pub key: Option<Vec<u8>>,
#[prost(bytes = "vec", tag = "3")]
pub r#type: Vec<u8>,
#[prost(bytes = "vec", optional, tag = "4")]
pub context: Option<Vec<u8>>,
#[prost(message, optional, tag = "5")]
pub op: Option<DtOp>,
#[prost(uint32, optional, tag = "6")]
pub w: Option<u32>,
#[prost(uint32, optional, tag = "7")]
pub dw: Option<u32>,
#[prost(uint32, optional, tag = "8")]
pub pw: Option<u32>,
#[prost(bool, optional, tag = "9")]
pub return_body: Option<bool>,
#[prost(uint32, optional, tag = "10")]
pub timeout: Option<u32>,
#[prost(bool, optional, tag = "11")]
pub sloppy_quorum: Option<bool>,
#[prost(uint32, optional, tag = "12")]
pub n_val: Option<u32>,
#[prost(bool, optional, tag = "13")]
pub include_context: Option<bool>,
}
impl WireValue for DtUpdateReq {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.DtUpdateReq")
}
}
#[derive(Clone, Eq, PartialEq, Message)]
pub struct DtUpdateResp {
#[prost(bytes = "vec", optional, tag = "1")]
pub key: Option<Vec<u8>>,
#[prost(bytes = "vec", optional, tag = "2")]
pub context: Option<Vec<u8>>,
#[prost(sint64, optional, tag = "3")]
pub counter_value: Option<i64>,
#[prost(bytes = "vec", repeated, tag = "4")]
pub set_value: Vec<Vec<u8>>,
#[prost(message, optional, boxed, tag = "5")]
pub map_value: Option<Box<MapValue>>,
#[prost(uint64, optional, tag = "6")]
pub hll_value: Option<u64>,
#[prost(bytes = "vec", repeated, tag = "7")]
pub gset_value: Vec<Vec<u8>>,
}
impl WireValue for DtUpdateResp {
fn wire_type_id() -> WireTypeId {
WireTypeId::new("riak.DtUpdateResp")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn counter_op_round_trips() {
let op = CounterOp {
increment: Some(-7),
};
let bytes = op.encode_to_vec();
let back = CounterOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
}
#[test]
fn set_op_round_trips() {
let op = SetOp {
adds: vec![b"alice".to_vec(), b"bob".to_vec()],
removes: vec![b"carol".to_vec()],
};
let bytes = op.encode_to_vec();
let back = SetOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
}
#[test]
fn dt_op_carries_at_most_one_payload() {
let op = DtOp {
counter_op: Some(CounterOp { increment: Some(5) }),
..DtOp::default()
};
let bytes = op.encode_to_vec();
let back = DtOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
assert!(back.set_op.is_none());
assert!(back.hll_op.is_none());
assert!(back.gset_op.is_none());
}
#[test]
fn dt_fetch_req_round_trips() {
let req = DtFetchReq {
bucket: b"counters".to_vec(),
key: b"hits".to_vec(),
r#type: b"counters".to_vec(),
r: Some(2),
pr: Some(1),
basic_quorum: Some(true),
notfound_ok: Some(false),
timeout: Some(5_000),
sloppy_quorum: None,
n_val: Some(3),
include_context: Some(true),
};
let bytes = req.encode_to_vec();
let back = DtFetchReq::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, req);
}
#[test]
fn dt_fetch_resp_round_trips_for_counter() {
let resp = DtFetchResp {
context: Some(b"opaque-ctx".to_vec()),
r#type: DATA_TYPE_COUNTER,
value: Some(DtValue {
counter_value: Some(42),
..DtValue::default()
}),
};
let bytes = resp.encode_to_vec();
let back = DtFetchResp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, resp);
assert_eq!(back.r#type, 1);
}
#[test]
fn dt_fetch_resp_round_trips_for_set() {
let resp = DtFetchResp {
context: Some(b"ctx".to_vec()),
r#type: DATA_TYPE_SET,
value: Some(DtValue {
set_value: vec![b"x".to_vec(), b"y".to_vec()],
..DtValue::default()
}),
};
let bytes = resp.encode_to_vec();
let back = DtFetchResp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, resp);
}
#[test]
fn dt_update_req_round_trips() {
let req = DtUpdateReq {
bucket: b"counters".to_vec(),
key: Some(b"hits".to_vec()),
r#type: b"counters".to_vec(),
context: Some(b"prev-ctx".to_vec()),
op: Some(DtOp {
counter_op: Some(CounterOp { increment: Some(3) }),
..DtOp::default()
}),
w: Some(2),
dw: Some(1),
pw: Some(1),
return_body: Some(true),
timeout: Some(2_500),
sloppy_quorum: None,
n_val: Some(3),
include_context: Some(true),
};
let bytes = req.encode_to_vec();
let back = DtUpdateReq::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, req);
}
#[test]
fn dt_update_resp_round_trips() {
let resp = DtUpdateResp {
key: Some(b"alice".to_vec()),
context: Some(b"new-ctx".to_vec()),
counter_value: Some(100),
set_value: vec![],
map_value: None,
hll_value: None,
gset_value: vec![],
};
let bytes = resp.encode_to_vec();
let back = DtUpdateResp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, resp);
}
#[test]
fn empty_resp_round_trips() {
let resp = DtUpdateResp::default();
let bytes = resp.encode_to_vec();
let back = DtUpdateResp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, resp);
}
#[test]
fn datatype_codes_match_riak_schema() {
assert_eq!(DATA_TYPE_COUNTER, 1);
assert_eq!(DATA_TYPE_SET, 2);
assert_eq!(DATA_TYPE_MAP, 3);
assert_eq!(DATA_TYPE_HLL, 4);
assert_eq!(DATA_TYPE_GSET, 5);
}
#[test]
fn pbc_codes_match_riak_schema() {
assert_eq!(DT_FETCH_REQ_CODE, 80);
assert_eq!(DT_FETCH_RESP_CODE, 81);
assert_eq!(DT_UPDATE_REQ_CODE, 82);
assert_eq!(DT_UPDATE_RESP_CODE, 83);
}
#[test]
fn map_field_round_trips() {
let f = MapField {
name: b"hits".to_vec(),
field_type: MAP_FIELD_TYPE_COUNTER,
};
let bytes = f.encode_to_vec();
let back = MapField::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, f);
}
#[test]
fn map_field_type_constants_are_canonical() {
assert_eq!(MAP_FIELD_TYPE_COUNTER, 1);
assert_eq!(MAP_FIELD_TYPE_SET, 2);
assert_eq!(MAP_FIELD_TYPE_REGISTER, 3);
assert_eq!(MAP_FIELD_TYPE_FLAG, 4);
assert_eq!(MAP_FIELD_TYPE_MAP, 5);
}
#[test]
fn scalar_op_round_trips_for_each_arm() {
let counter = ScalarOp {
counter_op: Some(CounterOp { increment: Some(3) }),
..ScalarOp::default()
};
let set = ScalarOp {
set_op: Some(SetOp {
adds: vec![b"a".to_vec()],
removes: vec![],
}),
..ScalarOp::default()
};
let register = ScalarOp {
register_op: Some(RegisterOp {
value: b"v".to_vec(),
ts_micros: Some(42),
}),
..ScalarOp::default()
};
let flag = ScalarOp {
flag_op: Some(FlagOp { enable: true }),
..ScalarOp::default()
};
for op in [counter, set, register, flag] {
let bytes = op.encode_to_vec();
let back = ScalarOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
}
}
#[test]
fn map_op_with_updates_and_removes_round_trips() {
let op = MapOp {
updates: vec![MapUpdate {
field: Some(MapField {
name: b"hits".to_vec(),
field_type: MAP_FIELD_TYPE_COUNTER,
}),
op: Some(ScalarOp {
counter_op: Some(CounterOp { increment: Some(7) }),
..ScalarOp::default()
}),
}],
removes: vec![MapField {
name: b"old".to_vec(),
field_type: MAP_FIELD_TYPE_FLAG,
}],
};
let bytes = op.encode_to_vec();
let back = MapOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
}
#[test]
fn nested_map_op_round_trips() {
let inner = MapOp {
updates: vec![MapUpdate {
field: Some(MapField {
name: b"inner".to_vec(),
field_type: MAP_FIELD_TYPE_COUNTER,
}),
op: Some(ScalarOp {
counter_op: Some(CounterOp { increment: Some(1) }),
..ScalarOp::default()
}),
}],
removes: vec![],
};
let outer = MapOp {
updates: vec![MapUpdate {
field: Some(MapField {
name: b"outer".to_vec(),
field_type: MAP_FIELD_TYPE_MAP,
}),
op: Some(ScalarOp {
map_op: Some(Box::new(inner)),
..ScalarOp::default()
}),
}],
removes: vec![],
};
let bytes = outer.encode_to_vec();
let back = MapOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, outer);
}
#[test]
fn map_value_round_trips() {
let value = MapValue {
entries: vec![
MapEntry {
field: Some(MapField {
name: b"hits".to_vec(),
field_type: MAP_FIELD_TYPE_COUNTER,
}),
value: Some(ScalarValue {
counter_value: Some(7),
..ScalarValue::default()
}),
},
MapEntry {
field: Some(MapField {
name: b"on".to_vec(),
field_type: MAP_FIELD_TYPE_FLAG,
}),
value: Some(ScalarValue {
flag_value: Some(true),
..ScalarValue::default()
}),
},
],
};
let bytes = value.encode_to_vec();
let back = MapValue::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, value);
}
#[test]
fn dt_op_with_map_payload_round_trips() {
let op = DtOp {
map_op: Some(Box::new(MapOp {
updates: vec![MapUpdate {
field: Some(MapField {
name: b"hits".to_vec(),
field_type: MAP_FIELD_TYPE_COUNTER,
}),
op: Some(ScalarOp {
counter_op: Some(CounterOp { increment: Some(2) }),
..ScalarOp::default()
}),
}],
removes: vec![],
})),
..DtOp::default()
};
let bytes = op.encode_to_vec();
let back = DtOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
assert!(back.counter_op.is_none());
assert!(back.set_op.is_none());
assert!(back.hll_op.is_none());
}
#[test]
fn dt_value_with_map_payload_round_trips() {
let value = DtValue {
map_value: Some(Box::new(MapValue {
entries: vec![MapEntry {
field: Some(MapField {
name: b"r".to_vec(),
field_type: MAP_FIELD_TYPE_REGISTER,
}),
value: Some(ScalarValue {
register_value: Some(b"hello".to_vec()),
..ScalarValue::default()
}),
}],
})),
..DtValue::default()
};
let bytes = value.encode_to_vec();
let back = DtValue::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, value);
}
#[test]
fn hll_op_add_value_round_trips() {
let op = HllOp {
add_value: vec![b"a".to_vec(), b"b".to_vec(), b"c".to_vec()],
};
let bytes = op.encode_to_vec();
let back = HllOp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, op);
}
#[test]
fn hll_value_round_trips() {
let v = HllValue {
cardinality: 12_345,
};
let bytes = v.encode_to_vec();
let back = HllValue::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, v);
}
#[test]
fn dt_update_resp_round_trips_with_map_value() {
let resp = DtUpdateResp {
key: Some(b"k".to_vec()),
context: None,
counter_value: None,
set_value: vec![],
map_value: Some(Box::new(MapValue {
entries: vec![MapEntry {
field: Some(MapField {
name: b"on".to_vec(),
field_type: MAP_FIELD_TYPE_FLAG,
}),
value: Some(ScalarValue {
flag_value: Some(true),
..ScalarValue::default()
}),
}],
})),
hll_value: None,
gset_value: vec![],
};
let bytes = resp.encode_to_vec();
let back = DtUpdateResp::decode(bytes.as_slice()).expect("decode");
assert_eq!(back, resp);
}
#[test]
fn itc_round_trips_through_dt_fetch_resp_context() {
use crate::datatypes::Itc;
let mut clock = Itc::seed();
clock.event();
clock.event();
let ctx = clock.encode();
let resp = DtFetchResp {
context: Some(ctx.clone()),
r#type: DATA_TYPE_COUNTER,
value: Some(DtValue {
counter_value: Some(7),
..DtValue::default()
}),
};
let bytes = resp.encode_to_vec();
let back = DtFetchResp::decode(bytes.as_slice()).expect("decode");
let echoed = back.context.expect("context present");
assert_eq!(echoed, ctx);
let recovered = Itc::decode(&echoed).expect("Itc decode");
assert_eq!(recovered, clock);
}
#[test]
fn itc_round_trips_through_dt_update_req_context() {
use crate::datatypes::Itc;
let mut clock = Itc::seed();
clock.event();
let ctx = clock.encode();
let req = DtUpdateReq {
bucket: b"b".to_vec(),
key: Some(b"k".to_vec()),
r#type: b"counters".to_vec(),
context: Some(ctx.clone()),
op: Some(DtOp {
counter_op: Some(CounterOp { increment: Some(1) }),
..DtOp::default()
}),
..DtUpdateReq::default()
};
let bytes = req.encode_to_vec();
let back = DtUpdateReq::decode(bytes.as_slice()).expect("decode");
let echoed = back.context.expect("context present");
let recovered = Itc::decode(&echoed).expect("Itc decode");
assert_eq!(recovered, clock);
}
#[test]
fn empty_itc_context_blob_round_trips() {
use crate::datatypes::Itc;
let ctx = Itc::seed().encode();
let resp = DtFetchResp {
context: Some(ctx.clone()),
r#type: DATA_TYPE_SET,
value: None,
};
let bytes = resp.encode_to_vec();
let back = DtFetchResp::decode(bytes.as_slice()).expect("decode");
let echoed = back.context.expect("context present");
let recovered = Itc::decode(&echoed).expect("Itc decode");
assert_eq!(recovered.event_tree(), &crate::datatypes::ItcEvent::Leaf(0));
}
}