use std::cmp::Ordering;
#[derive(Debug, PartialEq)]
pub enum Bit {
Zero,
One,
}
impl Bit {
pub fn to_u64(&self) -> u64 {
match self {
Bit::Zero => 0,
Bit::One => 1,
}
}
}
#[derive(Debug, Copy, serde::Deserialize, serde::Serialize)]
pub struct DataPoint {
time: u64,
value: f64,
}
impl Clone for DataPoint {
fn clone(&self) -> DataPoint {
*self
}
}
impl DataPoint {
pub fn new(time: u64, value: f64) -> Self {
DataPoint { time, value }
}
pub fn get_time(&self) -> u64 {
self.time
}
pub fn get_value(&self) -> f64 {
self.value
}
}
impl PartialEq for DataPoint {
#[inline]
fn eq(&self, other: &DataPoint) -> bool {
if self.time == other.time {
if self.value.is_nan() {
return other.value.is_nan();
} else {
return self.value == other.value;
}
}
false
}
}
impl Eq for DataPoint {}
impl Ord for DataPoint {
fn cmp(&self, other: &Self) -> Ordering {
self.time.cmp(&other.time)
}
}
impl PartialOrd for DataPoint {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
pub mod stream;
pub mod encode;
pub use self::encode::std_encoder::StdEncoder;
pub use self::encode::Encode;
pub mod decode;
pub use self::decode::std_decoder::StdDecoder;
pub use self::decode::Decode;
#[cfg(test)]
mod tests {
extern crate test_case;
use std::vec::Vec;
use super::decode::Error;
use super::stream::{BufferedReader, BufferedWriter};
use super::{DataPoint, Decode, Encode, StdDecoder, StdEncoder};
const DATA_1: &'static str = "1482892270,1.76
1482892280,7.78
1482892288,7.95
1482892292,5.53
1482892310,4.41
1482892323,5.30
1482892334,5.30
1482892341,2.92
1482892350,0.73
1482892360,-1.33
1482892370,-1.78
1482892390,-12.45
1482892401,-34.76
1482892490,78.9
1482892500,335.67
1482892800,12908.12
";
const DATA_2: &'static str = "0,0.0
1,0.0
5000,0.0";
#[test_case::test_case(1482892260, DATA_1 ; "a representative time series")]
#[test_case::test_case(0, DATA_2 ; "a time series with relatively large variation in times")]
fn integration_test(start_time: u64, data: &str) {
let w = BufferedWriter::new();
let mut encoder = StdEncoder::new(start_time, w);
let mut original_datapoints = Vec::new();
for line in data.lines() {
let substrings: Vec<&str> = line.split(",").collect();
let t = substrings[0].parse::<u64>().unwrap();
let v = substrings[1].parse::<f64>().unwrap();
let dp = DataPoint::new(t, v);
original_datapoints.push(dp);
}
for dp in &original_datapoints {
encoder.encode(*dp);
}
let bytes = encoder.close();
let r = BufferedReader::new(bytes);
let mut decoder = StdDecoder::new(r);
let mut new_datapoints = Vec::new();
let mut done = false;
loop {
if done {
break;
}
match decoder.next() {
Ok(dp) => new_datapoints.push(dp),
Err(err) => {
if err == Error::EndOfStream {
done = true;
} else {
panic!("Received an error from decoder: {:?}", err);
}
}
};
}
assert_eq!(original_datapoints, new_datapoints);
}
#[test]
fn data_point_ordering_test() {
let dp_1 = DataPoint::new(20, 2.0);
let dp_2 = DataPoint::new(10, 3.0);
let dp_3 = DataPoint::new(10, 3.0);
assert!(dp_2 < dp_1);
assert!(dp_2 == dp_3 && dp_1 != dp_2);
let dp_4 = DataPoint::new(10, f64::NAN);
let dp_5 = DataPoint::new(10, f64::NAN);
assert!(dp_4 == dp_5);
}
}