///|
pub struct ReplayEvent {
index_value : Int32
sequence_value : Int32?
rank_value : Int32
status_value : String
error_value : String?
}
///|
pub fn ReplayEvent::index(self : ReplayEvent) -> Int32 {
self.index_value
}
///|
pub fn ReplayEvent::sequence(self : ReplayEvent) -> Int32? {
self.sequence_value
}
///|
pub fn ReplayEvent::rank(self : ReplayEvent) -> Int32 {
self.rank_value
}
///|
pub fn ReplayEvent::status(self : ReplayEvent) -> String {
self.status_value
}
///|
pub fn ReplayEvent::error_kind(self : ReplayEvent) -> String? {
self.error_value
}
///|
fn error_kind(error : CodeError) -> String {
match error {
Invalid(_) => "invalid"
Shape(_) => "shape"
Limit(_) => "limit"
Inconsistent => "inconsistent"
Incomplete(_) => "incomplete"
Corrupt(_) => "corrupt"
Truncated => "truncated"
}
}
///|
pub fn ReplayEvent::to_json(self : ReplayEvent) -> String {
let sequence = match self.sequence_value {
Some(value) => value.to_string()
None => "null"
}
// Both status/error names are produced internally from fixed enumerations.
let error = match self.error_value {
Some(value) => "\"" + value + "\""
None => "null"
}
"{\"index\":" +
self.index_value.to_string() +
",\"sequence\":" +
sequence +
",\"rank\":" +
self.rank_value.to_string() +
",\"status\":\"" +
self.status_value +
"\",\"error\":" +
error +
"}"
}
///|
pub struct Replay {
decoder : Decoder
event_limit : Int32
event_values : Array[ReplayEvent]
mut rejection_count : Int32
}
///|
pub fn Replay::new(
generation : Generation,
max_events~ : Int32 = 4096,
) -> Replay raise CodeError {
{
decoder: Decoder::new(generation, max_packets=max_events),
event_limit: max_events,
event_values: [],
rejection_count: 0,
}
}
///|
fn Replay::record(
self : Replay,
parse : () -> Packet raise CodeError,
) -> ReplayEvent raise CodeError {
if self.event_values.length() == self.event_limit {
raise Limit("replay event budget exhausted")
}
let mut sequence : Int32? = None
let mut status = "rejected"
let mut error : String? = None
try {
let packet = parse()
sequence = Some(packet.sequence())
match self.decoder.admit(packet) {
Innovative(_, _) => status = "innovative"
Dependent => status = "dependent"
}
} catch {
failure => {
error = Some(error_kind(failure))
self.rejection_count = self.rejection_count + 1
}
}
let event : ReplayEvent = {
index_value: self.event_values.length(),
sequence_value: sequence,
rank_value: self.decoder.rank(),
status_value: status,
error_value: error,
}
self.event_values.push(event)
event
}
///|
pub fn Replay::feed_wire(
self : Replay,
frame : Symbols,
) -> ReplayEvent raise CodeError {
self.record(() => packet_from_wire(frame))
}
///|
pub fn Replay::feed_hex(
self : Replay,
text : String,
) -> ReplayEvent raise CodeError {
self.record(() => packet_from_hex(text))
}
///|
pub fn Replay::events(self : Replay) -> Array[ReplayEvent] {
let out : Array[ReplayEvent] = []
for event in self.event_values {
out.push(event)
}
out
}
///|
pub fn Replay::rejected(self : Replay) -> Int32 {
self.rejection_count
}
///|
pub fn Replay::report(self : Replay) -> DecodeReport {
self.decoder.report()
}
///|
pub fn Replay::recover(self : Replay) -> Symbols raise CodeError {
self.decoder.recover()
}