use std::collections::hash_map::{IntoIter, Iter};
use std::collections::HashMap;
use std::ops::{Deref, DerefMut};
use bincode::config::{standard, Configuration, Fixint, LittleEndian};
use bincode::{Decode as BincodeDecode, Encode as BincodeEncode};
use serde::{Deserialize as SerdeDeserialize, Serialize as SerdeSerialize};
use serde_json::Value as SerdeJsonValue;
use crate::rline_error::RlineError;
use crate::rline_error::RlineError::RuntimeError;
use crate::value::Value;
type WrappedType = HashMap<String, Value>;
const BINCODE_CONFIG: Configuration<LittleEndian, Fixint> = standard().with_fixed_int_encoding();
#[derive(
SerdeSerialize, SerdeDeserialize, BincodeDecode, BincodeEncode, Clone, Debug, PartialEq,
)]
pub struct Row(WrappedType);
impl Row {
pub fn new() -> Self {
Row(HashMap::new())
}
pub fn with_capacity(capacity: usize) -> Self {
Row(HashMap::with_capacity(capacity))
}
}
impl Default for Row {
fn default() -> Self {
Self::new()
}
}
impl Deref for Row {
type Target = WrappedType;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for Row {
fn deref_mut(&mut self) -> &mut WrappedType {
&mut self.0
}
}
type ConsumedItem = (String, Value);
type BorrowedItem<'a> = (&'a String, &'a Value);
impl IntoIterator for Row {
type Item = ConsumedItem;
type IntoIter = TableIntoIterator;
fn into_iter(self) -> Self::IntoIter {
TableIntoIterator {
iterator: self.0.into_iter(),
}
}
}
pub struct TableIntoIterator {
iterator: IntoIter<String, Value>,
}
impl Iterator for TableIntoIterator {
type Item = ConsumedItem;
fn next(&mut self) -> Option<ConsumedItem> {
self.iterator.next()
}
}
impl<'a> IntoIterator for &'a Row {
type Item = BorrowedItem<'a>;
type IntoIter = TableIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
TableIterator {
iterator: self.0.iter(),
}
}
}
pub struct TableIterator<'a> {
iterator: Iter<'a, String, Value>,
}
impl<'a> Iterator for TableIterator<'a> {
type Item = BorrowedItem<'a>;
fn next(&mut self) -> Option<BorrowedItem<'a>> {
self.iterator.next()
}
}
#[derive(SerdeDeserialize)]
pub enum SerializationFormat {
#[serde(alias = "json", alias = "JSON")]
Json,
#[serde(alias = "bincode", alias = "BINCODE")]
Bincode,
}
impl Row {
pub fn to_bytes_json(&self) -> Result<Vec<u8>, RlineError> {
serde_json::to_vec(self).map_err(|e| RlineError::runtime_error(&e))
}
pub fn to_bytes_bincode(&self) -> Result<Vec<u8>, RlineError> {
bincode::encode_to_vec(self, BINCODE_CONFIG).map_err(|e| RlineError::runtime_error(&e))
}
pub fn to_bytes_bincode_result(result: Result<Row, String>) -> Result<Vec<u8>, RlineError> {
bincode::encode_to_vec(result, BINCODE_CONFIG).map_err(|e| RlineError::runtime_error(&e))
}
pub fn to_bytes_json_result(result: Result<Row, String>) -> Result<Vec<u8>, RlineError> {
serde_json::to_vec(&result).map_err(|e| RlineError::runtime_error(&e))
}
pub fn from_bytes_json(from: &[u8]) -> Result<Self, RlineError> {
serde_json::from_slice(from).map_err(|e| RlineError::runtime_error(&e))
}
pub fn from_bytes_bincode(from: &[u8]) -> Result<Self, RlineError> {
let (decoded, _) = bincode::decode_from_slice(from, BINCODE_CONFIG)
.map_err(|e| RlineError::runtime_error(&e))?;
Ok(decoded)
}
pub fn from_bytes_json_result(from: &[u8]) -> Result<Self, RlineError> {
let decoded: Result<Self, String> =
serde_json::from_slice(from).map_err(|e| RlineError::runtime_error(&e))?;
decoded.map_err(RuntimeError)
}
pub fn from_bytes_bincode_result(from: &[u8]) -> Result<Self, RlineError> {
let (decoded, _): (Result<Self, String>, usize) =
bincode::decode_from_slice(from, BINCODE_CONFIG)
.map_err(|e| RlineError::runtime_error(&e))?;
decoded.map_err(RuntimeError)
}
fn json_value_to_row(json_value: SerdeJsonValue) -> Result<Row, RlineError> {
match json_value {
SerdeJsonValue::Null
| SerdeJsonValue::Bool(_)
| SerdeJsonValue::Number(_)
| SerdeJsonValue::String(_)
| SerdeJsonValue::Array(_) => Err(RuntimeError(
format!("Json value {} does not represent a row. A row is a map associating column names to their values.", json_value))
),
SerdeJsonValue::Object(map_key_value) => {
let mut row = Row::with_capacity(map_key_value.len());
for (column_name, json_value) in map_key_value {
row.insert(column_name, Value::from_json_value(json_value)?);
}
Ok(row)
}
}
}
pub fn from_bytes_json_infer_types(from: &[u8]) -> Result<Vec<Row>, RlineError> {
let json_value: SerdeJsonValue =
serde_json::from_slice(from).map_err(|e| RlineError::runtime_error(&e))?;
match json_value {
SerdeJsonValue::Null
| SerdeJsonValue::Bool(_)
| SerdeJsonValue::Number(_)
| SerdeJsonValue::String(_)
| SerdeJsonValue::Object(_) => Err(RuntimeError(format!(
"Json value {} does not represent a list of ros.",
json_value
))),
SerdeJsonValue::Array(values) => {
values.into_iter().map(Row::json_value_to_row).collect()
}
}
}
}
impl<const N: usize> From<[(String, Value); N]> for Row {
fn from(arr: [(String, Value); N]) -> Self {
Row(HashMap::from_iter(arr))
}
}
impl From<HashMap<String, Value>> for Row {
fn from(map: HashMap<String, Value>) -> Self {
Row(map)
}
}