serde_influxlp/
lib.rs

1//! # Serde InfluxDB V2 Line Protocol
2//!
3//! InfluxDB's line protocol is a text-based format used to represent data
4//! points. It includes the measurement, optional tag set, field set, and an
5//! optional timestamp.
6//!
7//! ```
8//! measurement         tag set             field set              timestamp
9//! ----------- ------------------- ------------------------- -------------------
10//! measurement,tag1=val1,tag2=val2 field1="val1",field2=true 1729270461612452700
11//! ```
12//!
13//! ## Limitations
14//! Unfortunately due to the required format of the line protocol (as seen
15//! above) the struct, although created by the user, has a required format that
16//! must be followed closely. Some serde features are also currently
17//! unsupported, e.g., tagging. Below are different examples of how to setup and
18//! customize your struct.
19//!
20//! This crate does not support any type which is not [supported](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#data-types-and-format) by InfluxDB v2
21//! Line Protocol. These types are:
22//!
23//! 1. Any number (int, uint, float)
24//! 2. Strings
25//! 3. Booleans
26//!
27//! In the line protocol tag keys-/values and field keys-/values also has [restricted types](https://docs.influxdata.com/influxdb/v2/reference/syntax/line-protocol/#elements-of-line-protocol). This crate supports serializing and deserializing back-and-forth from types. Bare in mind however that InfluxDB will treat the element value as its expected type.
28//!
29//! ## Examples
30//!
31//! Below is the bare minimum required in a struct to be serialized and
32//! deserialized successfully. At most one entry is required in the fields map.
33//! `Value` is a custom enum for this crate.
34//!
35//! ```rust
36//! use serde_influxlp::Value;
37//!
38//! #[derive(Debug, Serialize, Deserialize)]
39//! pub struct Metric {
40//!     pub measurement: String,
41//!
42//!     pub fields: HashMap<String, Value>,
43//! }
44//! ```
45//!
46//! </br>
47//!
48//! Tags and a timestamp field can also be added to the struct. If in some cases
49//! its uncertain whether the fields are present they can be marked as an
50//! `Option`. Timestamp should always be an i64 as in the line protocol
51//! timestamp is a unix timestamp with the same range as an i64.
52//!
53//! </br>
54//!
55//! ```rust
56//! use serde_influxlp::Value;
57//!
58//! #[derive(Debug, Serialize, Deserialize)]
59//! pub struct Tags {
60//!     pub tag1: i32,
61//!
62//!     pub tag2: Option<String>,
63//!     ...
64//! }
65//!
66//! #[derive(Debug, Serialize, Deserialize)]
67//! pub struct Metric {
68//!     pub measurement: String,
69//!
70//!     pub tags: Option<Tags>,
71//!
72//!     pub fields: HashMap<String, Value>,
73//!
74//!     pub timestamp: Option<i64>,
75//! }
76//! ```
77//!
78//! </br>
79//!
80//! Tags and fields can also be defined as structs of their own if the values
81//! are known beforehand, or if you only want to serialize/deserialize a few
82//! fields. As with the tags and timestamp these can be marked as an `Option`
83//!
84//! </br>
85//!
86//! ```rust
87//! use serde_influxlp::Value;
88//!
89//! #[derive(Debug, Serialize, Deserialize)]
90//! pub struct Tags {
91//!     pub tag1: i32,
92//!
93//!     pub tag2: Option<String>,
94//!     ...
95//! }
96//!
97//! #[derive(Debug, Serialize, Deserialize)]
98//! pub struct Fields {
99//!     pub field1: String,
100//!
101//!     pub field2: Option<bool>,
102//!     ...
103//! }
104//!
105//! #[derive(Debug, Serialize, Deserialize)]
106//! pub struct Metric {
107//!     pub measurement: String,
108//!
109//!     pub tags: Tags,
110//!
111//!     pub fields: Fields,
112//!
113//!     pub timestamp: i64,
114//! }
115//! ```
116//!
117//! </br>
118//!
119//! Enums are also supported
120//!
121//! </br>
122//!
123//! ```rust
124//! #[derive(Debug, Serialize, Deserialize)]
125//! #[serde(rename_all = "lowercase")]
126//! pub enum Measurement {
127//!     Metric1,
128//!     Metric2,
129//! }
130//!
131//! #[derive(Debug, Serialize, Deserialize)]
132//! pub struct Metric {
133//!     pub measurement: Measurement,
134//!
135//!     pub tags: Tags,
136//!
137//!     pub fields: Fields,
138//!
139//!     pub timestamp: i64,
140//! }
141//! ```
142//!
143//! </br>
144//!
145//! As said previously we require the field names to be as they are because they
146//! are used to ensure that the serialization and deserialization is done
147//! properly. If you want to rename the fields it can be done with serdes rename
148//! feature
149//!
150//! </br>
151//!
152//! ```rust
153//! #[derive(Debug, Serialize, Deserialize)]
154//! pub struct Metric {
155//!     #[serde(rename = "measurement")]
156//!     pub name: String,
157//!
158//!     #[serde(rename = "tags")]
159//!     pub tag_set: Tags,
160//!
161//!     #[serde(rename = "fields")]
162//!     pub field_set: Fields,
163//!
164//!     #[serde(rename = "timestamp")]
165//!     pub time: i64,
166//! }
167//! ```
168//!
169//! </br>
170//!
171//! ### Serialization and deserialization
172//! ```rust
173//! use serde_influxlp::Value;
174//!
175//! #[derive(Debug, Serialize, Deserialize)]
176//! #[serde(rename_all = "lowercase")]
177//! pub enum Measurement {
178//!     Metric1,
179//!     Metric2,
180//! }
181//!
182//! #[derive(Debug, Serialize, Deserialize)]
183//! pub struct Tags {
184//!     pub tag1: i32,
185//! }
186//!
187//! #[derive(Debug, Serialize, Deserialize)]
188//! pub struct Fields {
189//!     pub field1: String,
190//!
191//!     pub field2: Option<bool>,
192//! }
193//!
194//! #[derive(Debug, Serialize, Deserialize)]
195//! pub struct Metric {
196//!     pub measurement: Measurement,
197//!
198//!     pub tags: HashMap<String, Value>,
199//!
200//!     pub fields: Fields,
201//!
202//!     pub timestamp: Option<i64>,
203//! }
204//!
205//! fn main() {
206//!     let metric = Metric {
207//!         measurement: Measurement::Metric1,
208//!         tags: HashMap::from([
209//!             ("tag1".to_string(), Value::from(12.5)),
210//!             ("tag2".to_string(), Value::from(25)),
211//!         ]),
212//!         fields: Fields {
213//!             field1: "{\"hello\": \"world\"}".to_string(),
214//!             field2: None,
215//!         },
216//!         timestamp: Some(1577836800),
217//!     };
218//!
219//!     let string = serde_influxlp::to_string(&metric).unwrap();
220//!
221//!     // Output:
222//!     // metric1,tag1=10.5 field1="{\"hello\": \"world\"}" 1577836800
223//!
224//!     let metric: Metric = serde_influxlp::from_str(&string).unwrap()
225//!
226//!     // Output:
227//!     // Metric {
228//!     //     measurement: Metric1,
229//!     //     tags: {
230//!     //         "tag1": Float(
231//!     //             10.5,
232//!     //         ),
233//!     //     },
234//!     //     fields: Fields {
235//!     //         field1: "{\"hello\": \"world\"}",
236//!     //         field2: None,
237//!     //     },
238//!     //     timestamp: Some(1577836800),
239//!     // }
240//!
241//!     // A line protocol can also be made by hand
242//!     let string = "metric2 field1=\"Hello, reader!\",field2=t";
243//!     let metric: Metric = from_str(&string).unwrap();
244//!
245//!     // Output:
246//!     // Metric {
247//!     //     measurement: Metric2,
248//!     //     tags: None,
249//!     //     fields: Fields {
250//!     //         field1: "Hello, reader!",
251//!     //         field2: Some(
252//!     //             true,
253//!     //         ),
254//!     //     },
255//!     //     timestamp: None,
256//!     // }
257//! }
258//! ```
259//!
260//! Tip: You can deserialize a line protocol string to a struct, then add,
261//! remove, or edit its values before serializing again to change the line
262//! protocol.
263
264pub(crate) mod builder;
265pub(crate) mod datatypes;
266pub(crate) mod de;
267pub(crate) mod error;
268pub(crate) mod reader;
269pub(crate) mod ser;
270pub(crate) mod value;
271
272pub use crate::{
273    de::{from_reader, from_slice, from_str},
274    error::{Error, ErrorCode},
275    ser::{to_string, to_vec, to_writer},
276    value::{
277        datatypes::{Number, Value},
278        de::from_value,
279        ser::to_value,
280    },
281};