rinfluxdb_types/
lib.rs

1// Copyright Claudio Mattera 2021.
2// Distributed under the MIT License or Apache 2.0 License at your option.
3// See accompanying files License-MIT.txt and License-Apache-2.0, or online at
4// https://opensource.org/licenses/MIT
5// https://opensource.org/licenses/Apache-2.0
6
7//! Types used by other modules
8
9use std::fmt;
10
11use tracing::*;
12
13use thiserror::Error;
14
15use chrono::{DateTime, SecondsFormat, Utc};
16
17/// Value types supported by InfluxDB
18#[derive(Clone, Debug, PartialEq)]
19pub enum Value {
20    /// A floating point value
21    Float(f64),
22
23    /// An integer value
24    Integer(i64),
25
26    /// An unsigned integer value
27    UnsignedInteger(u64),
28
29    /// A string value
30    String(String),
31
32    /// A boolean value
33    Boolean(bool),
34
35    /// A datetime value (as nanosecond epoch)
36    Timestamp(DateTime<Utc>),
37}
38
39impl Value {
40    pub fn into_f64(self) -> f64 {
41        if let Value::Float(value) = self {
42            value
43        } else if let Value::Integer(value) = self {
44            value as f64
45        } else if let Value::UnsignedInteger(value) = self {
46            value as f64
47        } else {
48            panic!("Not a f64: {:?}", self);
49        }
50    }
51
52    pub fn into_i64(self) -> i64 {
53        if let Value::Integer(value) = self {
54            value
55        } else if let Value::UnsignedInteger(value) = self {
56            value as i64
57        } else if let Value::Float(value) = self {
58            warn!("Casting float to integer");
59            value as i64
60        } else {
61            panic!("Not a i64: {:?}", self);
62        }
63    }
64
65    pub fn into_u64(self) -> u64 {
66        if let Value::UnsignedInteger(value) = self {
67            value
68        } else {
69            panic!("Not a u64: {:?}", self);
70        }
71    }
72
73    pub fn into_boolean(self) -> bool {
74        if let Value::Boolean(value) = self {
75            value
76        } else {
77            panic!("Not a boolean: {:?}", self);
78        }
79    }
80
81    pub fn into_string(self) -> String {
82        if let Value::String(value) = self {
83            value
84        } else {
85            panic!("Not a string: {:?}", self);
86        }
87    }
88
89    pub fn into_timestamp(self) -> DateTime<Utc> {
90        if let Value::Timestamp(value) = self {
91            value
92        } else {
93            panic!("Not a timestamp: {:?}", self);
94        }
95    }
96}
97
98impl fmt::Display for Value {
99    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
100        match &self {
101            Value::Float(value) => {
102                write!(f, "{}", value)?;
103            }
104            Value::Integer(value) => {
105                write!(f, "{}", value)?;
106            }
107            Value::UnsignedInteger(value) => {
108                write!(f, "{}", value)?;
109            }
110            Value::String(value) => {
111                write!(f, "{}", value)?;
112            }
113            Value::Boolean(value) => {
114                write!(f, "{}", value)?;
115            }
116            Value::Timestamp(value) => {
117                write!(f, "{}", value)?;
118            }
119        }
120
121        Ok(())
122    }
123}
124
125/// A duration
126///
127/// Note: this type is almost entirely equivalent to `chrono::Duration`, but
128/// it also supports infinite duration in addition.
129///
130/// Since `chrono::Duration` implements `Into<Duration>`, the former can be
131/// used everywhere the latter is expected.
132#[derive(Debug)]
133pub enum Duration {
134    /// A duration expressed in nanoseconds
135    Nanoseconds(i64),
136
137    /// A duration expressed in microseconds
138    Microseconds(i64),
139
140    /// A duration expressed in milliseconds
141    Milliseconds(i64),
142
143    /// A duration expressed in seconds
144    Seconds(i64),
145
146    /// A duration expressed in minutes
147    Minutes(i64),
148
149    /// A duration expressed in hours
150    Hours(i64),
151
152    /// A duration expressed in days
153    Days(i64),
154
155    /// An infinite duration
156    Infinity,
157}
158
159impl ToString for Duration {
160    fn to_string(&self) -> String {
161        match self {
162            Duration::Nanoseconds(seconds) => format!("{}ns", seconds),
163            Duration::Microseconds(seconds) => format!("{}us", seconds),
164            Duration::Milliseconds(seconds) => format!("{}ms", seconds),
165            Duration::Seconds(seconds) => format!("{}s", seconds),
166            Duration::Minutes(minutes) => format!("{}m", minutes),
167            Duration::Hours(hours) => format!("{}h", hours),
168            Duration::Days(days) => format!("{}d", days),
169            Duration::Infinity => "inf".to_string(),
170        }
171    }
172}
173
174impl From<chrono::Duration> for Duration {
175    fn from(duration: chrono::Duration) -> Self {
176        Duration::Seconds(duration.num_seconds())
177    }
178}
179
180/// An entity which is either an instant or a duration
181///
182/// InfluxDB allows to use durations where instants are expected, and
183/// interprets them as the point in time relative to the current instant.
184/// E.g. if now is `2021-03-10T22:43:32Z`, the duration `Duration::Minutes(-4)`
185/// is interpreted as the instant `2021-03-10T22:39:32Z`.
186#[derive(Debug)]
187pub enum InstantOrDuration {
188    /// An instant in time
189    Instant(DateTime<Utc>),
190
191    /// The instant corresponding to the current time plus a duration
192    Duration(Duration),
193}
194
195impl ToString for InstantOrDuration {
196    fn to_string(&self) -> String {
197        match self {
198            InstantOrDuration::Instant(instant) => format!(
199                "'{}'",
200                instant.to_rfc3339_opts(SecondsFormat::AutoSi, true),
201            ),
202            InstantOrDuration::Duration(duration) => duration.to_string(),
203        }
204    }
205}
206
207impl From<DateTime<Utc>> for InstantOrDuration {
208    fn from(instant: DateTime<Utc>) -> Self {
209        InstantOrDuration::Instant(instant)
210    }
211}
212
213impl From<Duration> for InstantOrDuration {
214    fn from(duration: Duration) -> Self {
215        InstantOrDuration::Duration(duration)
216    }
217}
218
219impl From<chrono::Duration> for InstantOrDuration {
220    fn from(duration: chrono::Duration) -> Self {
221        InstantOrDuration::Duration(duration.into())
222    }
223}
224
225/// An error occurred while creating the dataframe
226#[derive(Error, Debug)]
227pub enum DataFrameError {
228    /// Error while creating the dataframe
229    #[error("Error while creating the dataframe")]
230    Creation,
231}