#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseEventHeaderError(pub String);
impl std::fmt::Display for ParseEventHeaderError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "unknown event header: {}", self.0)
}
}
impl std::error::Error for ParseEventHeaderError {}
sip_header::define_header_enum! {
error_type: ParseEventHeaderError,
pub enum EventHeader {
EventName => "Event-Name",
EventSubclass => "Event-Subclass",
UniqueId => "Unique-ID",
CallerUniqueId => "Caller-Unique-ID",
OtherLegUniqueId => "Other-Leg-Unique-ID",
ChannelCallUuid => "Channel-Call-UUID",
JobUuid => "Job-UUID",
ChannelName => "Channel-Name",
ChannelState => "Channel-State",
ChannelStateNumber => "Channel-State-Number",
ChannelCallState => "Channel-Call-State",
AnswerState => "Answer-State",
CallDirection => "Call-Direction",
HangupCause => "Hangup-Cause",
CallerCallerIdName => "Caller-Caller-ID-Name",
CallerCallerIdNumber => "Caller-Caller-ID-Number",
CallerOrigCallerIdName => "Caller-Orig-Caller-ID-Name",
CallerOrigCallerIdNumber => "Caller-Orig-Caller-ID-Number",
CallerCalleeIdName => "Caller-Callee-ID-Name",
CallerCalleeIdNumber => "Caller-Callee-ID-Number",
CallerDestinationNumber => "Caller-Destination-Number",
CallerContext => "Caller-Context",
CallerDirection => "Caller-Direction",
CallerNetworkAddr => "Caller-Network-Addr",
CoreUuid => "Core-UUID",
DtmfDigit => "DTMF-Digit",
Priority => "priority",
LogLevel => "Log-Level",
PlData => "pl_data",
SipEvent => "event",
SipContentType => "sip_content_type",
GatewayName => "gateway_name",
ChannelReadCodecName => "Channel-Read-Codec-Name",
ChannelReadCodecRate => "Channel-Read-Codec-Rate",
ChannelReadCodecBitRate => "Channel-Read-Codec-Bit-Rate",
ChannelReportedReadCodecRate => "Channel-Reported-Read-Codec-Rate",
ChannelWriteCodecName => "Channel-Write-Codec-Name",
ChannelWriteCodecRate => "Channel-Write-Codec-Rate",
ChannelWriteCodecBitRate => "Channel-Write-Codec-Bit-Rate",
ChannelReportedWriteCodecRate => "Channel-Reported-Write-Codec-Rate",
ChannelVideoReadCodecName => "Channel-Video-Read-Codec-Name",
ChannelVideoReadCodecRate => "Channel-Video-Read-Codec-Rate",
ChannelVideoWriteCodecName => "Channel-Video-Write-Codec-Name",
ChannelVideoWriteCodecRate => "Channel-Video-Write-Codec-Rate",
SessionCount => "Session-Count",
FreeswitchHostname => "FreeSWITCH-Hostname",
FreeswitchSwitchname => "FreeSWITCH-Switchname",
FreeswitchIpv4 => "FreeSWITCH-IPv4",
FreeswitchIpv6 => "FreeSWITCH-IPv6",
FreeswitchVersion => "FreeSWITCH-Version",
FreeswitchDomain => "FreeSWITCH-Domain",
FreeswitchUser => "FreeSWITCH-User",
Application => "Application",
ApplicationData => "Application-Data",
ApplicationResponse => "Application-Response",
ApplicationUuid => "Application-UUID",
EventDateLocal => "Event-Date-Local",
EventDateGmt => "Event-Date-GMT",
EventDateTimestamp => "Event-Date-Timestamp",
EventCallingFile => "Event-Calling-File",
EventCallingFunction => "Event-Calling-Function",
EventCallingLineNumber => "Event-Calling-Line-Number",
EventSequence => "Event-Sequence",
ChannelPresenceId => "Channel-Presence-ID",
ChannelPresenceData => "Channel-Presence-Data",
PresenceDataCols => "Presence-Data-Cols",
PresenceCallDirection => "Presence-Call-Direction",
ChannelHitDialplan => "Channel-HIT-Dialplan",
SessionExternalId => "Session-External-ID",
OtherType => "Other-Type",
ChannelCallStateNumber => "Channel-Call-State-Number",
OriginalChannelCallState => "Original-Channel-Call-State",
DtmfDuration => "DTMF-Duration",
DtmfSource => "DTMF-Source",
CallerLogicalDirection => "Caller-Logical-Direction",
CallerUsername => "Caller-Username",
CallerDialplan => "Caller-Dialplan",
CallerAni => "Caller-ANI",
CallerAniii => "Caller-ANI-II",
CallerSource => "Caller-Source",
CallerTransferSource => "Caller-Transfer-Source",
CallerRdnis => "Caller-RDNIS",
CallerChannelName => "Caller-Channel-Name",
CallerProfileIndex => "Caller-Profile-Index",
CallerScreenBit => "Caller-Screen-Bit",
CallerPrivacyHideName => "Caller-Privacy-Hide-Name",
CallerPrivacyHideNumber => "Caller-Privacy-Hide-Number",
OtherLegDirection => "Other-Leg-Direction",
OtherLegLogicalDirection => "Other-Leg-Logical-Direction",
OtherLegUsername => "Other-Leg-Username",
OtherLegDialplan => "Other-Leg-Dialplan",
OtherLegCallerIdName => "Other-Leg-Caller-ID-Name",
OtherLegCallerIdNumber => "Other-Leg-Caller-ID-Number",
OtherLegOrigCallerIdName => "Other-Leg-Orig-Caller-ID-Name",
OtherLegOrigCallerIdNumber => "Other-Leg-Orig-Caller-ID-Number",
OtherLegCalleeIdName => "Other-Leg-Callee-ID-Name",
OtherLegCalleeIdNumber => "Other-Leg-Callee-ID-Number",
OtherLegNetworkAddr => "Other-Leg-Network-Addr",
OtherLegAni => "Other-Leg-ANI",
OtherLegAniii => "Other-Leg-ANI-II",
OtherLegDestinationNumber => "Other-Leg-Destination-Number",
OtherLegSource => "Other-Leg-Source",
OtherLegTransferSource => "Other-Leg-Transfer-Source",
OtherLegContext => "Other-Leg-Context",
OtherLegRdnis => "Other-Leg-RDNIS",
OtherLegChannelName => "Other-Leg-Channel-Name",
OtherLegProfileIndex => "Other-Leg-Profile-Index",
OtherLegScreenBit => "Other-Leg-Screen-Bit",
OtherLegPrivacyHideName => "Other-Leg-Privacy-Hide-Name",
OtherLegPrivacyHideNumber => "Other-Leg-Privacy-Hide-Number",
UpTime => "Up-Time",
UptimeMsec => "Uptime-msec",
MaxSessions => "Max-Sessions",
SessionPeakMax => "Session-Peak-Max",
SessionPeakFiveMin => "Session-Peak-FiveMin",
SessionPerSec => "Session-Per-Sec",
SessionPerSecFiveMin => "Session-Per-Sec-FiveMin",
SessionPerSecMax => "Session-Per-Sec-Max",
SessionPerSecLast => "Session-Per-Sec-Last",
SessionSinceStartup => "Session-Since-Startup",
IdleCpu => "Idle-CPU",
HeartbeatInterval => "Heartbeat-Interval",
EventInfo => "Event-Info",
LogData => "Log-Data",
LogFile => "Log-File",
LogFunction => "Log-Function",
LogLine => "Log-Line",
UserData => "User-Data",
ApplicationUuidName => "Application-UUID-Name",
Gateway => "Gateway",
State => "State",
PingStatus => "Ping-Status",
Phrase => "Phrase",
ProfileName => "profile-name",
Status => "Status",
}
}
pub fn normalize_header_key(raw: &str) -> String {
if let Ok(eh) = raw.parse::<EventHeader>() {
return eh
.as_str()
.to_string();
}
if raw.contains('_') {
raw.to_string()
} else {
title_case_dashes(raw)
}
}
fn title_case_dashes(s: &str) -> String {
let mut result = String::with_capacity(s.len());
let mut capitalize_next = true;
for c in s.chars() {
if c == '-' {
result.push('-');
capitalize_next = true;
} else if capitalize_next {
result.push(c.to_ascii_uppercase());
capitalize_next = false;
} else {
result.push(c.to_ascii_lowercase());
}
}
result
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn display_round_trip() {
assert_eq!(EventHeader::UniqueId.to_string(), "Unique-ID");
assert_eq!(
EventHeader::ChannelCallState.to_string(),
"Channel-Call-State"
);
assert_eq!(
EventHeader::CallerCallerIdName.to_string(),
"Caller-Caller-ID-Name"
);
assert_eq!(EventHeader::Priority.to_string(), "priority");
}
#[test]
fn as_ref_str() {
let h: &str = EventHeader::UniqueId.as_ref();
assert_eq!(h, "Unique-ID");
}
#[test]
fn from_str_case_insensitive() {
assert_eq!(
"unique-id".parse::<EventHeader>(),
Ok(EventHeader::UniqueId)
);
assert_eq!(
"UNIQUE-ID".parse::<EventHeader>(),
Ok(EventHeader::UniqueId)
);
assert_eq!(
"Unique-ID".parse::<EventHeader>(),
Ok(EventHeader::UniqueId)
);
assert_eq!(
"channel-call-state".parse::<EventHeader>(),
Ok(EventHeader::ChannelCallState)
);
}
#[test]
fn from_str_unknown() {
let err = "X-Custom-Not-In-Enum".parse::<EventHeader>();
assert!(err.is_err());
assert_eq!(
err.unwrap_err()
.to_string(),
"unknown event header: X-Custom-Not-In-Enum"
);
}
#[test]
fn normalize_known_enum_variants_return_canonical_form() {
assert_eq!(normalize_header_key("unique-id"), "Unique-ID");
assert_eq!(normalize_header_key("UNIQUE-ID"), "Unique-ID");
assert_eq!(normalize_header_key("Unique-ID"), "Unique-ID");
assert_eq!(normalize_header_key("dtmf-digit"), "DTMF-Digit");
assert_eq!(normalize_header_key("DTMF-DIGIT"), "DTMF-Digit");
assert_eq!(
normalize_header_key("channel-call-uuid"),
"Channel-Call-UUID"
);
assert_eq!(normalize_header_key("event-name"), "Event-Name");
}
#[test]
fn normalize_known_underscore_variants_return_canonical_form() {
assert_eq!(normalize_header_key("priority"), "priority");
assert_eq!(normalize_header_key("PRIORITY"), "priority");
assert_eq!(normalize_header_key("pl_data"), "pl_data");
assert_eq!(normalize_header_key("PL_DATA"), "pl_data");
assert_eq!(normalize_header_key("sip_content_type"), "sip_content_type");
assert_eq!(normalize_header_key("gateway_name"), "gateway_name");
assert_eq!(normalize_header_key("event"), "event");
assert_eq!(normalize_header_key("EVENT"), "event");
}
#[test]
fn normalize_codec_headers_from_switch_core_codec() {
assert_eq!(
normalize_header_key("channel-read-codec-bit-rate"),
"Channel-Read-Codec-Bit-Rate"
);
assert_eq!(
normalize_header_key("Channel-Read-Codec-Bit-Rate"),
"Channel-Read-Codec-Bit-Rate"
);
assert_eq!(
normalize_header_key("Channel-Write-codec-bit-rate"),
"Channel-Write-Codec-Bit-Rate"
);
assert_eq!(
normalize_header_key("channel-video-read-codec-name"),
"Channel-Video-Read-Codec-Name"
);
}
#[test]
fn normalize_unknown_underscore_keys_passthrough() {
assert_eq!(
normalize_header_key("variable_sip_call_id"),
"variable_sip_call_id"
);
assert_eq!(
normalize_header_key("variable_sip_h_X-My-CUSTOM-Header"),
"variable_sip_h_X-My-CUSTOM-Header"
);
assert_eq!(
normalize_header_key("variable_sip_h_Diversion"),
"variable_sip_h_Diversion"
);
}
#[test]
fn normalize_unknown_dash_keys_title_case() {
assert_eq!(normalize_header_key("content-type"), "Content-Type");
assert_eq!(normalize_header_key("Content-Type"), "Content-Type");
assert_eq!(normalize_header_key("CONTENT-TYPE"), "Content-Type");
assert_eq!(normalize_header_key("x-custom-header"), "X-Custom-Header");
assert_eq!(
normalize_header_key("Content-Disposition"),
"Content-Disposition"
);
assert_eq!(normalize_header_key("reply-text"), "Reply-Text");
}
#[test]
fn normalize_idempotent_for_all_enum_variants() {
let variants = [
EventHeader::EventName,
EventHeader::UniqueId,
EventHeader::ChannelCallUuid,
EventHeader::DtmfDigit,
EventHeader::Priority,
EventHeader::PlData,
EventHeader::SipEvent,
EventHeader::GatewayName,
EventHeader::SipContentType,
EventHeader::ChannelReadCodecBitRate,
EventHeader::ChannelVideoWriteCodecRate,
EventHeader::LogLevel,
];
for v in variants {
let canonical = v.as_str();
assert_eq!(
normalize_header_key(canonical),
canonical,
"normalization not idempotent for {canonical}"
);
}
}
#[test]
fn parse_missing_event_default_headers() {
assert!("Event-Date-Local"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Date-GMT"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Date-Timestamp"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Calling-File"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Calling-Function"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Calling-Line-Number"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Sequence"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_missing_channel_basic_data_headers() {
assert!("Channel-Presence-ID"
.parse::<EventHeader>()
.is_ok());
assert!("Channel-Presence-Data"
.parse::<EventHeader>()
.is_ok());
assert!("Presence-Data-Cols"
.parse::<EventHeader>()
.is_ok());
assert!("Presence-Call-Direction"
.parse::<EventHeader>()
.is_ok());
assert!("Channel-HIT-Dialplan"
.parse::<EventHeader>()
.is_ok());
assert!("Session-External-ID"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Type"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_missing_callstate_and_dtmf_headers() {
assert!("Channel-Call-State-Number"
.parse::<EventHeader>()
.is_ok());
assert!("Original-Channel-Call-State"
.parse::<EventHeader>()
.is_ok());
assert!("DTMF-Duration"
.parse::<EventHeader>()
.is_ok());
assert!("DTMF-Source"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_missing_caller_profile_headers() {
assert!("Caller-Logical-Direction"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Username"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Dialplan"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-ANI"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-ANI-II"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Source"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Transfer-Source"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-RDNIS"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Channel-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Profile-Index"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Screen-Bit"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Privacy-Hide-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Caller-Privacy-Hide-Number"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_heartbeat_headers() {
assert!("Up-Time"
.parse::<EventHeader>()
.is_ok());
assert!("Uptime-msec"
.parse::<EventHeader>()
.is_ok());
assert!("Max-Sessions"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Peak-Max"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Peak-FiveMin"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Per-Sec"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Per-Sec-FiveMin"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Per-Sec-Max"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Per-Sec-Last"
.parse::<EventHeader>()
.is_ok());
assert!("Session-Since-Startup"
.parse::<EventHeader>()
.is_ok());
assert!("Idle-CPU"
.parse::<EventHeader>()
.is_ok());
assert!("Heartbeat-Interval"
.parse::<EventHeader>()
.is_ok());
assert!("Event-Info"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_log_headers() {
assert!("Log-Data"
.parse::<EventHeader>()
.is_ok());
assert!("Log-File"
.parse::<EventHeader>()
.is_ok());
assert!("Log-Function"
.parse::<EventHeader>()
.is_ok());
assert!("Log-Line"
.parse::<EventHeader>()
.is_ok());
assert!("User-Data"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_application_uuid_name() {
assert!("Application-UUID-Name"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn parse_sofia_event_headers() {
assert_eq!("Gateway".parse::<EventHeader>(), Ok(EventHeader::Gateway));
assert_eq!("State".parse::<EventHeader>(), Ok(EventHeader::State));
assert_eq!(
"Ping-Status".parse::<EventHeader>(),
Ok(EventHeader::PingStatus)
);
assert_eq!("Phrase".parse::<EventHeader>(), Ok(EventHeader::Phrase));
assert_eq!(
"profile-name".parse::<EventHeader>(),
Ok(EventHeader::ProfileName)
);
}
#[test]
fn parse_missing_other_leg_headers() {
assert!("Other-Leg-Direction"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Logical-Direction"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Username"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Dialplan"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Caller-ID-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Caller-ID-Number"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Orig-Caller-ID-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Orig-Caller-ID-Number"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Callee-ID-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Callee-ID-Number"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Network-Addr"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-ANI"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-ANI-II"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Destination-Number"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Source"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Transfer-Source"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Context"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-RDNIS"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Channel-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Profile-Index"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Screen-Bit"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Privacy-Hide-Name"
.parse::<EventHeader>()
.is_ok());
assert!("Other-Leg-Privacy-Hide-Number"
.parse::<EventHeader>()
.is_ok());
}
#[test]
fn from_str_round_trip_all_variants() {
let variants = [
EventHeader::EventName,
EventHeader::EventSubclass,
EventHeader::UniqueId,
EventHeader::CallerUniqueId,
EventHeader::OtherLegUniqueId,
EventHeader::ChannelCallUuid,
EventHeader::JobUuid,
EventHeader::ChannelName,
EventHeader::ChannelState,
EventHeader::ChannelStateNumber,
EventHeader::ChannelCallState,
EventHeader::AnswerState,
EventHeader::CallDirection,
EventHeader::HangupCause,
EventHeader::CallerCallerIdName,
EventHeader::CallerCallerIdNumber,
EventHeader::CallerOrigCallerIdName,
EventHeader::CallerOrigCallerIdNumber,
EventHeader::CallerCalleeIdName,
EventHeader::CallerCalleeIdNumber,
EventHeader::CallerDestinationNumber,
EventHeader::CallerContext,
EventHeader::CallerDirection,
EventHeader::CallerNetworkAddr,
EventHeader::CoreUuid,
EventHeader::DtmfDigit,
EventHeader::Priority,
EventHeader::LogLevel,
EventHeader::PlData,
EventHeader::SipEvent,
EventHeader::SipContentType,
EventHeader::GatewayName,
EventHeader::ChannelReadCodecName,
EventHeader::ChannelReadCodecRate,
EventHeader::ChannelReadCodecBitRate,
EventHeader::ChannelReportedReadCodecRate,
EventHeader::ChannelWriteCodecName,
EventHeader::ChannelWriteCodecRate,
EventHeader::ChannelWriteCodecBitRate,
EventHeader::ChannelReportedWriteCodecRate,
EventHeader::ChannelVideoReadCodecName,
EventHeader::ChannelVideoReadCodecRate,
EventHeader::ChannelVideoWriteCodecName,
EventHeader::ChannelVideoWriteCodecRate,
EventHeader::Application,
EventHeader::ApplicationData,
EventHeader::ApplicationResponse,
EventHeader::ApplicationUuid,
EventHeader::EventDateLocal,
EventHeader::EventDateGmt,
EventHeader::EventDateTimestamp,
EventHeader::EventCallingFile,
EventHeader::EventCallingFunction,
EventHeader::EventCallingLineNumber,
EventHeader::EventSequence,
EventHeader::ChannelPresenceId,
EventHeader::ChannelPresenceData,
EventHeader::PresenceDataCols,
EventHeader::PresenceCallDirection,
EventHeader::ChannelHitDialplan,
EventHeader::SessionExternalId,
EventHeader::OtherType,
EventHeader::ChannelCallStateNumber,
EventHeader::OriginalChannelCallState,
EventHeader::DtmfDuration,
EventHeader::DtmfSource,
EventHeader::CallerLogicalDirection,
EventHeader::CallerUsername,
EventHeader::CallerDialplan,
EventHeader::CallerAni,
EventHeader::CallerAniii,
EventHeader::CallerSource,
EventHeader::CallerTransferSource,
EventHeader::CallerRdnis,
EventHeader::CallerChannelName,
EventHeader::CallerProfileIndex,
EventHeader::CallerScreenBit,
EventHeader::CallerPrivacyHideName,
EventHeader::CallerPrivacyHideNumber,
EventHeader::OtherLegDirection,
EventHeader::OtherLegLogicalDirection,
EventHeader::OtherLegUsername,
EventHeader::OtherLegDialplan,
EventHeader::OtherLegCallerIdName,
EventHeader::OtherLegCallerIdNumber,
EventHeader::OtherLegOrigCallerIdName,
EventHeader::OtherLegOrigCallerIdNumber,
EventHeader::OtherLegCalleeIdName,
EventHeader::OtherLegCalleeIdNumber,
EventHeader::OtherLegNetworkAddr,
EventHeader::OtherLegAni,
EventHeader::OtherLegAniii,
EventHeader::OtherLegDestinationNumber,
EventHeader::OtherLegSource,
EventHeader::OtherLegTransferSource,
EventHeader::OtherLegContext,
EventHeader::OtherLegRdnis,
EventHeader::OtherLegChannelName,
EventHeader::OtherLegProfileIndex,
EventHeader::OtherLegScreenBit,
EventHeader::OtherLegPrivacyHideName,
EventHeader::OtherLegPrivacyHideNumber,
EventHeader::UpTime,
EventHeader::UptimeMsec,
EventHeader::MaxSessions,
EventHeader::SessionPeakMax,
EventHeader::SessionPeakFiveMin,
EventHeader::SessionPerSec,
EventHeader::SessionPerSecFiveMin,
EventHeader::SessionPerSecMax,
EventHeader::SessionPerSecLast,
EventHeader::SessionSinceStartup,
EventHeader::IdleCpu,
EventHeader::HeartbeatInterval,
EventHeader::EventInfo,
EventHeader::LogData,
EventHeader::LogFile,
EventHeader::LogFunction,
EventHeader::LogLine,
EventHeader::UserData,
EventHeader::ApplicationUuidName,
EventHeader::Gateway,
EventHeader::State,
EventHeader::PingStatus,
EventHeader::Phrase,
EventHeader::ProfileName,
EventHeader::Status,
];
for v in variants {
let wire = v.to_string();
let parsed: EventHeader = wire
.parse()
.unwrap();
assert_eq!(parsed, v, "round-trip failed for {wire}");
}
}
}