1use std::{fmt::Display, str::FromStr};
18
19use anyhow::Context;
20use regex::Regex;
21
22use crate::traits::{Convert, Format};
23
24#[derive(Debug, Clone, Hash, PartialEq, Eq)]
25pub struct Measurement(pub String);
26
27impl From<&str> for Measurement {
28 fn from(value: &str) -> Self {
29 Measurement(value.to_string())
30 }
31}
32
33impl From<&String> for Measurement {
34 fn from(value: &String) -> Self {
35 Measurement(value.to_owned())
36 }
37}
38
39impl From<String> for Measurement {
40 fn from(value: String) -> Self {
41 Measurement(value)
42 }
43}
44
45impl Display for Measurement {
46 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
47 write!(f, "{}", self.0)
48 }
49}
50
51impl Convert for Measurement {
52 fn parse_from<T>(from: T) -> anyhow::Result<Self>
63 where
64 Self: Sized,
65 T: ToString,
66 {
67 Ok(Measurement(from.to_string()))
68 }
69
70 fn parse_into<T>(&self) -> anyhow::Result<T>
78 where
79 T: FromStr,
80 <T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
81 {
82 let t = self.0.parse::<T>()?;
83 Ok(t)
84 }
85}
86
87impl Format for Measurement {
88 fn escape(&self) -> Self {
89 Measurement(self.0.replace(" ", r"\ ").replace(",", r"\,"))
90 }
91
92 fn unescape(&self) -> Self {
93 Measurement(self.0.replace(r"\,", ",").replace(r"\ ", " "))
94 }
95}
96
97#[derive(Debug, Clone, Hash, PartialEq, Eq)]
98pub struct TagKey(pub String);
99
100impl From<&str> for TagKey {
101 fn from(value: &str) -> Self {
102 TagKey(value.to_string())
103 }
104}
105
106impl From<&String> for TagKey {
107 fn from(value: &String) -> Self {
108 TagKey(value.to_owned())
109 }
110}
111
112impl From<String> for TagKey {
113 fn from(value: String) -> Self {
114 TagKey(value)
115 }
116}
117
118impl Display for TagKey {
119 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
120 write!(f, "{}", self.0)
121 }
122}
123
124impl Convert for TagKey {
125 fn parse_from<T>(from: T) -> anyhow::Result<Self>
136 where
137 Self: Sized,
138 T: ToString,
139 {
140 Ok(TagKey(from.to_string()))
141 }
142
143 fn parse_into<T>(&self) -> anyhow::Result<T>
151 where
152 T: FromStr,
153 <T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
154 {
155 let t = self.0.parse::<T>()?;
156 Ok(t)
157 }
158}
159
160impl Format for TagKey {
161 fn escape(&self) -> Self {
162 TagKey(
163 self.0
164 .replace(" ", r"\ ")
165 .replace(",", r"\,")
166 .replace("=", r"\="),
167 )
168 }
169
170 fn unescape(&self) -> Self {
171 TagKey(
172 self.0
173 .replace(r"\=", "=")
174 .replace(r"\,", ",")
175 .replace(r"\ ", " "),
176 )
177 }
178}
179
180#[derive(Debug, Clone, PartialEq, Eq)]
181pub struct TagValue(pub String);
182
183impl From<&str> for TagValue {
184 fn from(value: &str) -> Self {
185 TagValue(value.to_string())
186 }
187}
188
189impl From<&String> for TagValue {
190 fn from(value: &String) -> Self {
191 TagValue(value.to_owned())
192 }
193}
194
195impl From<String> for TagValue {
196 fn from(value: String) -> Self {
197 TagValue(value)
198 }
199}
200
201impl Display for TagValue {
202 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
203 write!(f, "{}", self.0)
204 }
205}
206
207impl Convert for TagValue {
208 fn parse_from<T>(from: T) -> anyhow::Result<Self>
219 where
220 Self: Sized,
221 T: ToString,
222 {
223 Ok(TagValue(from.to_string()))
224 }
225
226 fn parse_into<T>(&self) -> anyhow::Result<T>
234 where
235 T: FromStr,
236 <T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
237 {
238 let t = self.0.parse::<T>()?;
239 Ok(t)
240 }
241}
242
243impl Format for TagValue {
244 fn escape(&self) -> Self {
245 TagValue(
246 self.0
247 .replace(" ", r"\ ")
248 .replace(",", r"\,")
249 .replace("=", r"\="),
250 )
251 }
252
253 fn unescape(&self) -> Self {
254 TagValue(
255 self.0
256 .replace(r"\=", "=")
257 .replace(r"\,", ",")
258 .replace(r"\ ", " "),
259 )
260 }
261}
262
263#[derive(Debug, Clone, Hash, PartialEq, Eq)]
264pub struct FieldKey(pub String);
265
266impl From<&str> for FieldKey {
267 fn from(value: &str) -> Self {
268 FieldKey(value.to_string())
269 }
270}
271
272impl From<&String> for FieldKey {
273 fn from(value: &String) -> Self {
274 FieldKey(value.to_owned())
275 }
276}
277
278impl From<String> for FieldKey {
279 fn from(value: String) -> Self {
280 FieldKey(value)
281 }
282}
283
284impl Display for FieldKey {
285 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
286 write!(f, "{}", self.0)
287 }
288}
289
290impl Convert for FieldKey {
291 fn parse_from<T>(from: T) -> anyhow::Result<Self>
302 where
303 Self: Sized,
304 T: ToString,
305 {
306 Ok(FieldKey(from.to_string()))
307 }
308
309 fn parse_into<T>(&self) -> anyhow::Result<T>
317 where
318 T: FromStr,
319 <T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
320 {
321 let t = self.0.parse::<T>()?;
322 Ok(t)
323 }
324}
325
326impl Format for FieldKey {
327 fn escape(&self) -> Self {
328 FieldKey(
329 self.0
330 .replace(" ", r"\ ")
331 .replace(",", r"\,")
332 .replace("=", r"\="),
333 )
334 }
335
336 fn unescape(&self) -> Self {
337 FieldKey(
338 self.0
339 .replace(r"\=", "=")
340 .replace(r"\,", ",")
341 .replace(r"\ ", " "),
342 )
343 }
344}
345
346#[derive(Debug, Clone)]
347pub enum FieldValue {
348 Float(f64),
350
351 Integer(i64),
353
354 UInteger(u64),
356
357 String(String),
359
360 Boolean(bool),
362}
363
364impl From<&str> for FieldValue {
365 fn from(value: &str) -> Self {
366 FieldValue::String(value.to_owned())
367 }
368}
369
370impl From<&String> for FieldValue {
371 fn from(value: &String) -> Self {
372 FieldValue::String(value.to_owned())
373 }
374}
375
376impl From<String> for FieldValue {
377 fn from(value: String) -> Self {
378 FieldValue::String(value)
379 }
380}
381
382impl From<f32> for FieldValue {
383 fn from(value: f32) -> Self {
384 FieldValue::Float(value.into())
385 }
386}
387
388impl From<f64> for FieldValue {
389 fn from(value: f64) -> Self {
390 FieldValue::Float(value)
391 }
392}
393
394impl From<i8> for FieldValue {
395 fn from(value: i8) -> Self {
396 FieldValue::Integer(value.into())
397 }
398}
399
400impl From<i16> for FieldValue {
401 fn from(value: i16) -> Self {
402 FieldValue::Integer(value.into())
403 }
404}
405
406impl From<i32> for FieldValue {
407 fn from(value: i32) -> Self {
408 FieldValue::Integer(value.into())
409 }
410}
411
412impl From<i64> for FieldValue {
413 fn from(value: i64) -> Self {
414 FieldValue::Integer(value)
415 }
416}
417
418impl From<u8> for FieldValue {
419 fn from(value: u8) -> Self {
420 FieldValue::UInteger(value.into())
421 }
422}
423
424impl From<u16> for FieldValue {
425 fn from(value: u16) -> Self {
426 FieldValue::UInteger(value.into())
427 }
428}
429
430impl From<u32> for FieldValue {
431 fn from(value: u32) -> Self {
432 FieldValue::UInteger(value.into())
433 }
434}
435
436impl From<u64> for FieldValue {
437 fn from(value: u64) -> Self {
438 FieldValue::UInteger(value)
439 }
440}
441
442impl From<bool> for FieldValue {
443 fn from(value: bool) -> Self {
444 FieldValue::Boolean(value)
445 }
446}
447
448impl Display for FieldValue {
449 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
450 let value = match self {
451 FieldValue::Float(number) => format!("{number}"),
452 FieldValue::Integer(number) => format!("{number}i"),
453 FieldValue::UInteger(number) => format!("{number}i"),
454 FieldValue::String(string) => format!("{string}"),
455 FieldValue::Boolean(boolean) => format!("{boolean}"),
456 };
457
458 write!(f, "{}", value)
459 }
460}
461
462impl PartialEq for FieldValue {
463 fn eq(&self, other: &Self) -> bool {
464 self.to_string() == other.to_string()
465 }
466}
467
468impl Convert for FieldValue {
469 fn parse_from<T>(from: T) -> anyhow::Result<Self>
477 where
478 Self: Sized,
479 T: ToString,
480 {
481 let s = from.to_string();
482
483 let re = Regex::new(r"^-?\d+i$").unwrap();
485 if re.is_match(&s) {
486 let mut number = s.to_string();
488 number.pop();
489
490 let value = match number.starts_with("-") {
491 true => {
492 let int = number
493 .parse::<i64>()
494 .with_context(|| format!("number {s} is not a valid integer"))?;
495
496 FieldValue::Integer(int)
497 }
498 false => {
499 let uint = number
500 .parse::<u64>()
501 .with_context(|| format!("number {s} is not a valid unsigned integer"))?;
502
503 FieldValue::UInteger(uint)
504 }
505 };
506
507 return Ok(value);
508 };
509
510 if let Ok(number) = s.parse::<f64>() {
512 return Ok(FieldValue::Float(number));
513 }
514
515 let value = match s.as_ref() {
517 "t" | "T" | "true" | "True" | "TRUE" => FieldValue::Boolean(true),
518 "f" | "F" | "false" | "False" | "FALSE" => FieldValue::Boolean(false),
519 _ => FieldValue::String(s.to_string()),
520 };
521
522 Ok(value)
523 }
524
525 fn parse_into<T>(&self) -> anyhow::Result<T>
535 where
536 T: FromStr,
537 <T as FromStr>::Err: std::error::Error + Send + Sync + 'static,
538 {
539 let r = match self {
540 FieldValue::Float(number) => number.to_string(),
541 FieldValue::Integer(number) => number.to_string(),
542 FieldValue::UInteger(number) => number.to_string(),
543 FieldValue::String(string) => string.to_string(),
544 FieldValue::Boolean(bool) => bool.to_string(),
545 }
546 .parse::<T>()?;
547
548 Ok(r)
549 }
550}
551
552impl Format for FieldValue {
553 fn escape(&self) -> Self {
554 match self {
555 FieldValue::String(string) => {
556 let escaped = string.replace("\\", "\\\\").replace("\"", "\\\"");
557 FieldValue::String(format!("\"{escaped}\""))
558 }
559 other => other.clone(),
560 }
561 }
562
563 fn unescape(&self) -> Self {
564 match self {
565 FieldValue::String(string) => {
566 let unescaped = match string.starts_with("\"") && string.ends_with("\"") {
567 true => &string[1..string.len() - 1],
568 false => string.as_str(),
569 };
570 FieldValue::String(unescaped.replace("\\\"", "\"").replace("\\\\", "\\"))
571 }
572 other => other.clone(),
573 }
574 }
575}
576
577#[cfg(test)]
578mod test {
579 use super::*;
580
581 #[test]
582 fn test_tag_key_escape_unescape() {
583 let key = TagKey::from("some, value=");
584 let escaped_key = key.escape();
585
586 assert_eq!(escaped_key.to_string(), "some\\,\\ value\\=");
587
588 let unescaped_key = escaped_key.unescape();
589 assert_eq!(unescaped_key.to_string(), "some, value=");
590 }
591
592 #[test]
593 fn test_tag_value_escape_unescape() {
594 let value = TagValue::from("some, value=");
595 let escaped_value = value.escape();
596
597 assert_eq!(escaped_value.to_string(), "some\\,\\ value\\=");
598
599 let unescaped_value = escaped_value.unescape();
600 assert_eq!(unescaped_value.to_string(), "some, value=");
601 }
602
603 #[test]
604 fn test_field_key_escape_unescape() {
605 let key = FieldKey::from("some, value=");
606 let escaped_key = key.escape();
607
608 assert_eq!(escaped_key.to_string(), "some\\,\\ value\\=");
609
610 let unescaped_key = escaped_key.unescape();
611 assert_eq!(unescaped_key.to_string(), "some, value=");
612 }
613
614 #[test]
615 fn test_field_value_escape_unescape() {
616 let value = FieldValue::from("{\"foo\": [\"bar=\\baz\"]}");
618 let escaped_value = value.escape();
619
620 assert_eq!(
621 escaped_value.to_string(),
622 "\"{\\\"foo\\\": [\\\"bar=\\\\baz\\\"]}\""
623 );
624
625 let unescaped_value = escaped_value.unescape();
626 assert_eq!(unescaped_value.to_string(), "{\"foo\": [\"bar=\\baz\"]}");
627 }
628
629 #[test]
630 fn test_field_value_parse_float() {
631 let parsed = FieldValue::parse_from("10.0").unwrap();
632 let expected = FieldValue::Float(10.);
633 assert_eq!(parsed, expected)
634 }
635
636 #[test]
637 fn test_field_value_parse_signed_integer() {
638 let parsed = FieldValue::parse_from("-10i").unwrap();
639 let expected = FieldValue::Integer(-10);
640 assert_eq!(parsed, expected);
641
642 let parsed = FieldValue::parse_from("10i").unwrap();
643 let expected = FieldValue::Integer(10);
644 assert_eq!(parsed, expected)
645 }
646
647 #[test]
648 fn test_field_value_parse_unsigned_integer() {
649 let parsed = FieldValue::parse_from("9223372036854775808i").unwrap();
651 let expected = FieldValue::UInteger(9223372036854775808);
652 assert_eq!(parsed, expected);
653 }
654
655 #[test]
656 fn test_field_value_parse_boolean() {
657 let true_variants = vec!["t", "T", "true", "True", "TRUE"];
658 for variant in true_variants {
659 let parsed = FieldValue::parse_from(variant).unwrap();
660 let expected = FieldValue::Boolean(true);
661 assert_eq!(parsed, expected);
662 }
663
664 let false_variants = vec!["f", "F", "false", "False", "FALSE"];
665 for variant in false_variants {
666 let parsed = FieldValue::parse_from(variant).unwrap();
667 let expected = FieldValue::Boolean(false);
668 assert_eq!(parsed, expected);
669 }
670 }
671
672 #[test]
673 fn test_field_value_display() {
674 assert_eq!(FieldValue::Float(10.0).to_string(), "10");
675 assert_eq!(FieldValue::Float(10.5).to_string(), "10.5");
676 assert_eq!(FieldValue::Integer(10).to_string(), "10i");
677 assert_eq!(FieldValue::UInteger(10).to_string(), "10i");
678 assert_eq!(FieldValue::String("hello".to_string()).to_string(), "hello");
679 assert_eq!(FieldValue::Boolean(true).to_string(), "true");
680 assert_eq!(FieldValue::Boolean(false).to_string(), "false");
681 }
682}