freeswitch_log_parser/fields/
kind.rs1use std::cmp::{Ordering, Reverse};
5use std::fmt;
6use std::ops::Range;
7
8#[non_exhaustive]
14#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
15pub enum FieldKind {
16 ChannelName,
18 CallerIdName,
20 CallerIdNumber,
22 DestinationNumber,
24 CallId,
26 Uuid,
28 IpAddr,
31 VariableValue,
36}
37
38impl FieldKind {
39 pub fn label(&self) -> &'static str {
41 match self {
42 FieldKind::ChannelName => "channel-name",
43 FieldKind::CallerIdName => "caller-id-name",
44 FieldKind::CallerIdNumber => "caller-id-number",
45 FieldKind::DestinationNumber => "destination-number",
46 FieldKind::CallId => "call-id",
47 FieldKind::Uuid => "uuid",
48 FieldKind::IpAddr => "ip-addr",
49 FieldKind::VariableValue => "variable-value",
50 }
51 }
52}
53
54impl fmt::Display for FieldKind {
55 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56 f.pad(self.label())
57 }
58}
59
60#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
66pub enum FieldLocation {
67 Message,
69 Attached(usize),
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct Field {
78 pub kind: FieldKind,
79 pub at: FieldLocation,
80 pub range: Range<usize>,
81}
82
83#[non_exhaustive]
88#[derive(Debug, Clone, PartialEq, Eq)]
89pub enum RenderError {
90 OutOfBounds {
92 at: FieldLocation,
93 range: Range<usize>,
94 len: usize,
95 },
96 NotOnCharBoundary {
98 at: FieldLocation,
99 range: Range<usize>,
100 },
101 OverlappingSpans {
104 at: FieldLocation,
105 first: Range<usize>,
106 second: Range<usize>,
107 },
108}
109
110impl fmt::Display for RenderError {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 match self {
113 RenderError::OutOfBounds { at, range, len } => write!(
114 f,
115 "span {}..{} is past the end of {at} ({len} bytes)",
116 range.start, range.end
117 ),
118 RenderError::NotOnCharBoundary { at, range } => write!(
119 f,
120 "span {}..{} splits a character in {at}",
121 range.start, range.end
122 ),
123 RenderError::OverlappingSpans { at, first, second } => write!(
124 f,
125 "replaced spans {}..{} and {}..{} partially overlap in {at}",
126 first.start, first.end, second.start, second.end
127 ),
128 }
129 }
130}
131
132impl std::error::Error for RenderError {}
133
134impl fmt::Display for FieldLocation {
135 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136 match self {
137 FieldLocation::Message => f.pad("the message"),
138 FieldLocation::Attached(i) => write!(f, "attached line {i}"),
139 }
140 }
141}
142
143#[derive(Debug, Clone, PartialEq, Eq)]
145pub struct RenderedEntry {
146 pub message: String,
147 pub attached: Vec<String>,
148}
149fn kind_rank(kind: FieldKind) -> u8 {
152 match kind {
153 FieldKind::ChannelName => 0,
154 FieldKind::CallerIdName => 1,
155 FieldKind::CallerIdNumber => 2,
156 FieldKind::DestinationNumber => 3,
157 FieldKind::CallId => 4,
158 FieldKind::IpAddr => 5,
159 FieldKind::VariableValue => 6,
160 FieldKind::Uuid => 7,
161 }
162}
163
164pub(super) fn span_order(a: &Range<usize>, b: &Range<usize>) -> Ordering {
167 (a.start, Reverse(a.end)).cmp(&(b.start, Reverse(b.end)))
168}
169
170pub(super) fn field_order(a: &Field, b: &Field) -> Ordering {
172 span_order(&a.range, &b.range).then(kind_rank(a.kind).cmp(&kind_rank(b.kind)))
173}