use std::fmt;
use crate::attached::AttachedLines;
use crate::codec::{CodecMedia, CodecOffer, CodecParseError};
use crate::decode::truncate_at_char_boundary;
use crate::level::LogLevel;
use crate::line::LineKind;
use crate::message::{MessageKind, SdpDirection};
use super::collision::MOD_LOGFILE_BUF_SIZE;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum Block {
ChannelData {
fields: Vec<(String, String)>,
variables: Vec<(String, String)>,
},
Sdp {
direction: SdpDirection,
body: Vec<String>,
},
CodecNegotiation {
media: CodecMedia,
comparisons: Vec<(CodecOffer, CodecOffer)>,
matched: Vec<CodecOffer>,
near_matched: Vec<CodecOffer>,
},
}
#[cfg(feature = "sdp")]
impl Block {
pub fn sdp_codecs(
&self,
) -> Option<Result<freeswitch_types::sdp::SdpCodecs, freeswitch_types::sdp::SdpCodecError>>
{
let Block::Sdp { body, .. } = self else {
return None;
};
let text = body.join("\n");
if text.trim().is_empty() {
return None;
}
Some(freeswitch_types::sdp::SdpCodecs::parse(&text))
}
}
pub(super) const WARNING_EXCERPT_LEN: usize = 80;
#[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive]
pub enum ParseWarning {
UnclosedVariable { name: String },
UnparseableChannelData { line: String },
UnrecognizedCodecLine {
line: String,
source: Option<CodecParseError>,
},
UnexpectedCodecContinuation { line: String },
OversizeLine { bytes: usize },
}
impl ParseWarning {
pub(crate) fn excerpt(msg: &str) -> String {
truncate_at_char_boundary(msg, WARNING_EXCERPT_LEN).to_string()
}
}
impl fmt::Display for ParseWarning {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
ParseWarning::UnclosedVariable { name } => {
write!(f, "unclosed multi-line variable: {name}")
}
ParseWarning::UnparseableChannelData { line } => {
write!(f, "unparseable CHANNEL_DATA line: {line}")
}
ParseWarning::UnrecognizedCodecLine {
line,
source: Some(e),
} => write!(f, "unrecognized codec negotiation line ({e}): {line}"),
ParseWarning::UnrecognizedCodecLine { line, source: None } => {
write!(f, "unrecognized codec negotiation line: {line}")
}
ParseWarning::UnexpectedCodecContinuation { line } => {
write!(f, "unexpected codec negotiation continuation: {line}")
}
ParseWarning::OversizeLine { bytes } => write!(
f,
"line exceeds mod_logfile {MOD_LOGFILE_BUF_SIZE}-byte buffer \
({bytes} bytes), data may be truncated"
),
}
}
}
#[derive(Debug)]
pub struct LogEntry {
pub uuid: String,
pub timestamp: String,
pub level: Option<LogLevel>,
pub idle_pct: Option<String>,
pub source: Option<String>,
pub message: String,
pub kind: LineKind,
pub message_kind: MessageKind,
pub block: Option<Block>,
pub attached: AttachedLines,
pub line_number: u64,
pub warnings: Vec<ParseWarning>,
}