1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use std::{
    collections::HashMap,
    fmt::Display,
    time::{SystemTime, UNIX_EPOCH},
};

use crate::Precision;

/// Use this struct to write data to a bucket.
pub struct WriteQuery<'a, T: Display> {
    pub name: &'a str,
    pub tags: HashMap<&'a str, &'a str>,
    pub field_name: &'a str,
    pub value: T,
    pub timestamp: Option<(SystemTime, Precision)>,
}

impl<'a, T: Display> WriteQuery<'a, T> {
    pub fn new(
        name: &'a str,
        tags: HashMap<&'a str, &'a str>,
        field_name: &'a str,
        value: T,
        timestamp: Option<(SystemTime, Precision)>,
    ) -> Self {
        Self {
            name,
            tags,
            field_name,
            value,
            timestamp,
        }
    }

    fn format_tags(&self) -> String {
        if self.tags.is_empty() {
            String::new()
        } else {
            self.tags
                .iter()
                .map(|(k, v)| format!(",{}={}", k, v))
                .collect()
        }
    }

    fn format_timestamp(&self) -> String {
        if let Some((system_time, precision)) = &self.timestamp {
            // We are just going to assume that the system time is after the UNIX Epoch
            let ts = system_time
                .duration_since(UNIX_EPOCH)
                .expect("SystemTime before UNIX Epoch");
            format!(
                " {}",
                match precision {
                    Precision::h => (ts.as_secs() as u128) / 3600,
                    Precision::s => (ts.as_secs() as u128),
                    Precision::ms => (ts.as_millis() as u128),
                    Precision::us => (ts.as_micros() as u128),
                    Precision::ns => (ts.as_nanos() as u128),
                }
            )
        } else {
            String::new()
        }
    }
}

impl<'a, T: Display> Display for WriteQuery<'a, T> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(
            f,
            "{}{} {}={}{}",
            self.name,
            self.format_tags(),
            self.field_name,
            self.value,
            self.format_timestamp(),
        )
    }
}