use crate::error::LrrError;
use chrono::prelude::{DateTime, Local};
use std::{
collections::{
hash_map::{IntoIter, Iter, Keys},
HashMap,
},
convert::Into,
iter::IntoIterator,
};
#[derive(Debug, Clone)]
pub enum RecordValue {
Scalar(f32),
DateTime(DateTime<Local>),
Array1(Vec<f32>),
Array2(Vec<f32>, [usize; 2]),
Array3(Vec<f32>, [usize; 3]),
String(String),
}
#[derive(Debug)]
pub struct Record(HashMap<String, RecordValue>);
impl Record {
pub fn empty() -> Self {
Self { 0: HashMap::new() }
}
pub fn from_scalar(name: impl Into<String>, value: f32) -> Self {
Self {
0: HashMap::from([(name.into(), RecordValue::Scalar(value))]),
}
}
pub fn from_slice<K: Into<String> + Clone>(s: &[(K, RecordValue)]) -> Self {
Self(
s.iter()
.map(|(k, v)| (k.clone().into(), v.clone()))
.collect(),
)
}
pub fn keys(&self) -> Keys<String, RecordValue> {
self.0.keys()
}
pub fn insert(&mut self, k: impl Into<String>, v: RecordValue) {
self.0.insert(k.into(), v);
}
pub fn iter(&self) -> Iter<'_, String, RecordValue> {
self.0.iter()
}
pub fn into_iter_in_record(self) -> IntoIter<String, RecordValue> {
self.0.into_iter()
}
pub fn get(&self, k: &str) -> Option<&RecordValue> {
self.0.get(k)
}
pub fn merge(self, record: Record) -> Self {
Record(self.0.into_iter().chain(record.0).collect())
}
pub fn merge_inplace(&mut self, record: Record) {
for (k, v) in record.iter() {
self.0.insert(k.clone(), v.clone());
}
}
pub fn get_scalar(&self, k: &str) -> Result<f32, LrrError> {
if let Some(v) = self.0.get(k) {
match v {
RecordValue::Scalar(v) => Ok(*v as _),
_ => Err(LrrError::RecordValueTypeError("Scalar".to_string())),
}
} else {
Err(LrrError::RecordKeyError(k.to_string()))
}
}
pub fn get_array1(&self, k: &str) -> Result<Vec<f32>, LrrError> {
if let Some(v) = self.0.get(k) {
match v {
RecordValue::Array1(v) => Ok(v.clone()),
_ => Err(LrrError::RecordValueTypeError("Array1".to_string())),
}
} else {
Err(LrrError::RecordKeyError(k.to_string()))
}
}
pub fn get_array2(&self, k: &str) -> Result<(Vec<f32>, [usize; 2]), LrrError> {
if let Some(v) = self.0.get(k) {
match v {
RecordValue::Array2(v, s) => Ok((v.clone(), s.clone())),
_ => Err(LrrError::RecordValueTypeError("Array2".to_string())),
}
} else {
Err(LrrError::RecordKeyError(k.to_string()))
}
}
pub fn get_array3(&self, k: &str) -> Result<(Vec<f32>, [usize; 3]), LrrError> {
if let Some(v) = self.0.get(k) {
match v {
RecordValue::Array3(v, s) => Ok((v.clone(), s.clone())),
_ => Err(LrrError::RecordValueTypeError("Array3".to_string())),
}
} else {
Err(LrrError::RecordKeyError(k.to_string()))
}
}
pub fn get_string(&self, k: &str) -> Result<String, LrrError> {
if let Some(v) = self.0.get(k) {
match v {
RecordValue::String(s) => Ok(s.clone()),
_ => Err(LrrError::RecordValueTypeError("String".to_string())),
}
} else {
Err(LrrError::RecordKeyError(k.to_string()))
}
}
pub fn is_empty(&self) -> bool {
self.0.len() == 0
}
pub fn get_scalar_without_key(&self) -> Option<f32> {
if self.0.len() != 1 {
return None;
} else {
let key = self.0.keys().next().unwrap();
match self.0.get(key) {
Some(RecordValue::Scalar(value)) => Some(*value),
_ => None,
}
}
}
}