use std::collections::HashMap;
use std::fmt::{Debug, Display, Formatter};
use yad_core::constants::error::ErrorMessage;
use yad_core::constants::length::ByteLength;
use yad_core::Value;
use crate::constants::{ROW_END_HEADER, ROW_NAME_HEADER, ROW_START_HEADER};
use crate::error::{MALFORMED_ROW_NAME_VECTOR, MALFORMED_ROW_VECTOR};
use crate::key::Key;
use crate::{encode_name, segment_keys, usize_from_slice_bytes};
#[derive(Clone, Eq, PartialEq)]
pub struct Row {
pub name: String,
pub keys: HashMap<String, Key>,
}
impl Row {
pub fn new<S: ToString>(name: S, keys: Vec<Key>) -> Self {
let keys = keys
.into_iter()
.map(|item| (item.name.to_owned(), item))
.collect();
Self {
name: name.to_string(),
keys,
}
}
pub fn new_empty<S: ToString>(name: S) -> Self {
Self {
name: name.to_string(),
keys: HashMap::new(),
}
}
pub fn get_keys(&self) -> &HashMap<String, Key> {
&self.keys
}
pub fn get_keys_mut(&mut self) -> &mut HashMap<String, Key> {
&mut self.keys
}
pub fn insert_key<S: ToString>(&mut self, name: S, value: Value) {
let rows = self.get_keys_mut();
rows.insert(name.to_string(), Key::new(name, value));
}
pub fn remove_key<S: ToString>(&mut self, name: S) -> Option<Key> {
let rows = self.get_keys_mut();
rows.remove(&name.to_string())
}
fn byte_is_row_start_header(byte: u8) -> bool {
ROW_START_HEADER == byte
}
fn byte_is_row_end_header(byte: u8) -> bool {
ROW_END_HEADER == byte
}
fn byte_is_row_name_header(byte: u8) -> bool {
ROW_NAME_HEADER == (byte & 0xF0)
}
fn check_boundary_bytes(bytes: &Vec<u8>) -> bool {
let Some(first) = bytes.first() else {
return false;
};
let Some(last) = bytes.last() else {
return false;
};
Self::byte_is_row_start_header(*first) && Self::byte_is_row_end_header(*last)
}
fn find_and_decode_name_from_bytes(bytes: Vec<u8>) -> Option<String> {
if bytes.is_empty() {
return None;
}
let first = *bytes.get(0)?;
if !Self::byte_is_row_name_header(first) {
return None;
}
let byte_length = ByteLength::try_from(first).ok()?;
let be_length = usize_from_slice_bytes(&bytes[1..], byte_length)?;
let metadata_length = 1 + byte_length.as_byte_count() as usize;
if bytes.len() < metadata_length + be_length {
return None;
}
let string_bytes = &bytes[metadata_length..metadata_length + be_length];
String::from_utf8(string_bytes.to_vec()).ok()
}
pub fn serialize(&self) -> Result<Vec<u8>, ErrorMessage> {
let mut bytes: Vec<u8> = vec![ROW_START_HEADER];
bytes.extend_from_slice(encode_name(&self.name, ROW_NAME_HEADER)?.as_slice());
for (_n, value) in &self.keys {
bytes.extend_from_slice(value.serialize()?.as_slice());
}
bytes.push(ROW_END_HEADER);
Ok(bytes)
}
pub fn deserialize(bytes: Vec<u8>) -> Result<Self, ErrorMessage> {
if !Self::check_boundary_bytes(&bytes) {
return Err(ErrorMessage(MALFORMED_ROW_VECTOR));
}
let mut keys: Vec<Key> = vec![];
for key_bytes in segment_keys(&bytes) {
keys.push(Key::deserialize(key_bytes)?)
}
let name = Self::find_and_decode_name_from_bytes(bytes[1..].to_vec())
.ok_or_else(|| ErrorMessage(MALFORMED_ROW_NAME_VECTOR))?;
Ok(Self::new(name, keys))
}
}
impl Display for Row {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut keys: Vec<String> = vec![];
for (_name, key) in &self.keys {
keys.push(format!("{}", key))
}
write!(f, "{} = {{ {} }}", self.name, keys.join("; "))
}
}
impl Debug for Row {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let mut keys: Vec<String> = vec![];
for (_name, key) in &self.keys {
keys.push(format!("{:?}", key))
}
write!(f, "{} = {{ {} }}", self.name, keys.join("; "))
}
}