use std::fmt;
use std::ops::Range;
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum FieldKind {
ChannelName,
CallerIdName,
CallerIdNumber,
DestinationNumber,
CallId,
Uuid,
SipUri,
IpAddr,
}
impl FieldKind {
pub fn label(&self) -> &'static str {
match self {
FieldKind::ChannelName => "channel-name",
FieldKind::CallerIdName => "caller-id-name",
FieldKind::CallerIdNumber => "caller-id-number",
FieldKind::DestinationNumber => "destination-number",
FieldKind::CallId => "call-id",
FieldKind::Uuid => "uuid",
FieldKind::SipUri => "sip-uri",
FieldKind::IpAddr => "ip-addr",
}
}
}
impl fmt::Display for FieldKind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.pad(self.label())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum FieldLocation {
Message,
Attached(usize),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Field {
pub kind: FieldKind,
pub at: FieldLocation,
pub range: Range<usize>,
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RenderError {
OutOfBounds {
at: FieldLocation,
range: Range<usize>,
len: usize,
},
NotOnCharBoundary {
at: FieldLocation,
range: Range<usize>,
},
OverlappingSpans {
at: FieldLocation,
first: Range<usize>,
second: Range<usize>,
},
}
impl fmt::Display for RenderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
RenderError::OutOfBounds { at, range, len } => write!(
f,
"span {}..{} is past the end of {at} ({len} bytes)",
range.start, range.end
),
RenderError::NotOnCharBoundary { at, range } => write!(
f,
"span {}..{} splits a character in {at}",
range.start, range.end
),
RenderError::OverlappingSpans { at, first, second } => write!(
f,
"replaced spans {}..{} and {}..{} partially overlap in {at}",
first.start, first.end, second.start, second.end
),
}
}
}
impl std::error::Error for RenderError {}
impl fmt::Display for FieldLocation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
FieldLocation::Message => f.pad("the message"),
FieldLocation::Attached(i) => write!(f, "attached line {i}"),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RenderedEntry {
pub message: String,
pub attached: Vec<String>,
}
pub(super) fn kind_rank(kind: FieldKind) -> u8 {
match kind {
FieldKind::ChannelName => 0,
FieldKind::CallerIdName => 1,
FieldKind::CallerIdNumber => 2,
FieldKind::DestinationNumber => 3,
FieldKind::CallId => 4,
FieldKind::SipUri => 5,
FieldKind::IpAddr => 6,
FieldKind::Uuid => 7,
}
}