use rmp_serde::Serializer;
use serde::Serialize;
use crate::{
db::{
plugin_meta::{PluginMeta, PluginMetaKey},
query_index::QueryFilter,
},
errors::AtomicResult,
resources::PropVals,
};
#[tracing::instrument(skip_all)]
pub fn encode_propvals(propvals: &PropVals) -> AtomicResult<Vec<u8>> {
let bin =
rmp_serde::to_vec(&propvals).map_err(|e| format!("Could not serialize PropVals: {}", e))?;
Ok(bin)
}
#[tracing::instrument(skip_all)]
pub fn decode_propvals(bin: &[u8]) -> AtomicResult<PropVals> {
let propvals: PropVals =
rmp_serde::from_slice(bin).map_err(|e| format!("Could not deserialize PropVals: {}", e))?;
Ok(propvals)
}
impl super::query_index::QueryFilter {
#[tracing::instrument(skip_all)]
pub fn encode(&self) -> AtomicResult<Vec<u8>> {
let drive_bytes = self.drive.as_str().as_bytes();
let drive_len = u32::try_from(drive_bytes.len())
.map_err(|_| "QueryFilter drive string exceeds u32::MAX")?;
let mut rest_bin = Vec::new();
let rest = QueryFilterRest {
filters: &self.filters,
sort_by: &self.sort_by,
};
rest.serialize(&mut Serializer::new(&mut rest_bin))
.map_err(|e| format!("Error encoding QueryFilter rest: {}", e))?;
let mut out = Vec::with_capacity(4 + drive_bytes.len() + rest_bin.len());
out.extend_from_slice(&drive_len.to_le_bytes());
out.extend_from_slice(drive_bytes);
out.extend_from_slice(&rest_bin);
Ok(out)
}
#[tracing::instrument(skip_all)]
pub fn from_bytes(bytes: &[u8]) -> AtomicResult<QueryFilter> {
if bytes.len() < 4 {
return Err("QueryFilter bytes too short to contain drive length".into());
}
let drive_len = u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]) as usize;
let end_drive = 4usize.checked_add(drive_len).ok_or("drive_len overflow")?;
if bytes.len() < end_drive {
return Err("QueryFilter bytes truncated before drive_bytes".into());
}
let drive_str = std::str::from_utf8(&bytes[4..end_drive])
.map_err(|e| format!("QueryFilter drive is not valid UTF-8: {e}"))?;
let drive = crate::Subject::from(drive_str.to_string());
let rest: QueryFilterRestOwned = rmp_serde::from_slice(&bytes[end_drive..])
.map_err(|e| format!("Error decoding QueryFilter rest: {}", e))?;
Ok(QueryFilter {
filters: rest.filters,
sort_by: rest.sort_by,
drive,
})
}
pub fn drive_scan_prefix(drive_str: &str) -> Vec<u8> {
let drive_bytes = drive_str.as_bytes();
let drive_len = drive_bytes.len() as u32;
let mut out = Vec::with_capacity(4 + drive_bytes.len());
out.extend_from_slice(&drive_len.to_le_bytes());
out.extend_from_slice(drive_bytes);
out
}
}
#[derive(Serialize)]
struct QueryFilterRest<'a> {
filters: &'a Vec<crate::db::query_index::PropVal>,
sort_by: &'a Option<String>,
}
#[derive(serde::Deserialize)]
struct QueryFilterRestOwned {
filters: Vec<crate::db::query_index::PropVal>,
sort_by: Option<String>,
}
impl crate::db::plugin_meta::PluginMeta {
pub fn encode(&self) -> AtomicResult<Vec<u8>> {
let mut buf = Vec::new();
self.serialize(&mut Serializer::new(&mut buf))
.map_err(|e| format!("Failed to encode PluginMeta: {}", e))?;
Ok(buf)
}
pub fn from_bytes(bytes: &[u8]) -> AtomicResult<PluginMeta> {
let plugin_meta: PluginMeta = rmp_serde::from_slice(bytes)
.map_err(|e| format!("Failed to decode PluginMeta: {}", e))?;
Ok(plugin_meta)
}
}
impl crate::db::plugin_meta::PluginMetaKey {
pub fn encode(&self) -> AtomicResult<Vec<u8>> {
let mut buf = Vec::new();
self.serialize(&mut Serializer::new(&mut buf))
.map_err(|e| format!("Failed to encode PluginMetaKey: {}", e))?;
Ok(buf)
}
pub fn from_bytes(bytes: &[u8]) -> AtomicResult<PluginMetaKey> {
let plugin_meta_key: PluginMetaKey = rmp_serde::from_slice(bytes)
.map_err(|e| format!("Failed to decode PluginMetaKey: {}", e))?;
Ok(plugin_meta_key)
}
}