Update mod.rs
Add parser for key/value pairs to be indexed. Measurement and field are represented as _m and _f respectively.pull/24376/head
parent
5d80d5e100
commit
7f2f4eaceb
|
@ -1,4 +1,6 @@
|
|||
use std::str::Chars;
|
||||
use std::{error, fmt};
|
||||
use std::fs::read;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct Point {
|
||||
|
@ -7,6 +9,74 @@ pub struct Point {
|
|||
pub value: i64,
|
||||
}
|
||||
|
||||
impl Point {
|
||||
// TODO: handle escapes in the line protocol for , = and \t
|
||||
/// index_pairs parses the series key into key value pairs for insertion into the index. In
|
||||
/// cases where this series is already in the database, this parse step can be skipped entirely.
|
||||
/// The measurement is represented as a _m key and field as _f.
|
||||
pub fn index_pairs(&self) -> Result<Vec<Pair>, ParseError> {
|
||||
let mut chars = self.series.chars();
|
||||
let mut pairs = vec![];
|
||||
let mut key = "_m".to_string();
|
||||
let mut value = String::with_capacity(250);
|
||||
let mut reading_key = false;
|
||||
|
||||
while let Some(ch) = chars.next() {
|
||||
match ch {
|
||||
',' => {
|
||||
reading_key = true;
|
||||
pairs.push(Pair{key, value});
|
||||
key = String::with_capacity(250);
|
||||
value = String::with_capacity(250);
|
||||
},
|
||||
'=' => {
|
||||
reading_key = false;
|
||||
},
|
||||
'\t' => {
|
||||
reading_key = false;
|
||||
pairs.push(Pair{key, value});
|
||||
key = "_f".to_string();
|
||||
value = String::with_capacity(250);
|
||||
},
|
||||
_ => {
|
||||
if reading_key {
|
||||
key.push(ch);
|
||||
} else {
|
||||
value.push(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
pairs.push(Pair{key, value});
|
||||
|
||||
Ok(pairs)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub struct Pair {
|
||||
pub key: String,
|
||||
pub value: String,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseError {
|
||||
description: String,
|
||||
}
|
||||
|
||||
impl fmt::Display for ParseError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}", self.description)
|
||||
}
|
||||
}
|
||||
|
||||
impl error::Error for ParseError {
|
||||
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
|
||||
// Generic error, underlying cause isn't tracked.
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: have parse return an error for invalid inputs
|
||||
pub fn parse(input: &str) -> Vec<Point> {
|
||||
let mut points = Vec::with_capacity(10000);
|
||||
|
@ -98,4 +168,16 @@ mod test {
|
|||
assert_eq!(vals[1].time, 1234);
|
||||
assert_eq!(vals[1].value, 5);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn index_pairs() {
|
||||
let p = Point{series: "cpu,host=A,region=west\tusage_system".to_string(), value: 0, time: 0};
|
||||
let pairs = p.index_pairs().unwrap();
|
||||
assert_eq!(pairs, vec![
|
||||
Pair{key: "_m".to_string(), value: "cpu".to_string()},
|
||||
Pair{key: "host".to_string(), value: "A".to_string()},
|
||||
Pair{key: "region".to_string(), value: "west".to_string()},
|
||||
Pair{key: "_f".to_string(), value: "usage_system".to_string()},
|
||||
]);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue