mod append;
mod chunk;
#[cfg(feature = "storage_macro_dbc")]
mod dbc;
mod fs;
mod redis;
use crate::StorageEntry;
type Error = Box<dyn std::error::Error + Send + Sync + 'static>;
impl crate::application::CoLink {
pub(crate) fn _parse_macro(&self, key_name: &str) -> (String, String, String) {
let split_key = key_name.split(':').collect::<Vec<&str>>();
let mut macro_type = String::new();
for s in split_key.iter().rev() {
if s.contains('$') {
macro_type = s.to_string();
break;
}
}
let macro_type_splitter = format!(":{}", macro_type);
let split_by_macro = key_name.split(¯o_type_splitter).collect::<Vec<&str>>();
let mut string_after = split_by_macro[split_by_macro.len() - 1].to_string();
if string_after.starts_with(':') {
string_after = string_after[1..].to_string();
}
(
split_by_macro[0..(split_by_macro.len() - 1)].join(¯o_type_splitter),
macro_type.replace('$', ""),
string_after,
)
}
pub(crate) async fn _sm_create_entry(
&self,
key_name: &str,
payload: &[u8],
) -> Result<String, Error> {
let (string_before, macro_type, string_after) = self._parse_macro(key_name);
match macro_type.as_str() {
"chunk" => self._create_entry_chunk(&string_before, payload).await,
"redis" => {
self._create_entry_redis(&string_before, &string_after, payload)
.await
}
"fs" => {
self._create_entry_fs(&string_before, &string_after, payload)
.await
}
_ => Err(format!(
"invalid storage macro, found {} in key name {}",
macro_type, key_name
)
.into()),
}
}
pub(crate) async fn _sm_read_entry(&self, key_name: &str) -> Result<Vec<u8>, Error> {
let key_name = if key_name.contains("::") {
&key_name
[key_name.find(':').unwrap() + 2..key_name.rfind('@').unwrap_or(key_name.len())]
} else {
key_name
};
let (string_before, macro_type, string_after) = self._parse_macro(key_name);
match macro_type.as_str() {
"chunk" => self._read_entry_chunk(&string_before).await,
"redis" => self._read_entry_redis(&string_before, &string_after).await,
#[cfg(feature = "storage_macro_dbc")]
"dbc" => self._read_entry_dbc(&string_before, &string_after).await,
#[cfg(not(feature = "storage_macro_dbc"))]
"dbc" => Err(format!(
"Storage Macro DBC feature not enabled, but found $dbc in key name: {}",
key_name
)
.into()),
"fs" => self._read_entry_fs(&string_before, &string_after).await,
_ => Err(format!(
"invalid storage macro, found {} in key name {}",
macro_type, key_name
)
.into()),
}
}
pub(crate) async fn _sm_update_entry(
&self,
key_name: &str,
payload: &[u8],
) -> Result<String, Error> {
let (string_before, macro_type, string_after) = self._parse_macro(key_name);
match macro_type.as_str() {
"chunk" => self._update_entry_chunk(&string_before, payload).await,
"redis" => {
self._update_entry_redis(&string_before, &string_after, payload)
.await
}
"fs" => {
self._update_entry_fs(&string_before, &string_after, payload)
.await
}
"append" => self._update_entry_append(&string_before, payload).await,
_ => Err(format!(
"invalid storage macro, found {} in key name {}",
macro_type, key_name
)
.into()),
}
}
pub(crate) async fn _sm_delete_entry(&self, key_name: &str) -> Result<String, Error> {
let (string_before, macro_type, string_after) = self._parse_macro(key_name);
match macro_type.as_str() {
"chunk" => self._delete_entry_chunk(&string_before).await,
"redis" => {
self._delete_entry_redis(&string_before, &string_after)
.await
}
"fs" => self._delete_entry_fs(&string_before, &string_after).await,
_ => Err(format!(
"invalid storage macro, found {} in key name {}",
macro_type, key_name
)
.into()),
}
}
pub(crate) async fn _sm_read_keys(
&self,
prefix: &str,
include_history: bool,
) -> Result<Vec<StorageEntry>, Error> {
if include_history {
return Err("Storage Macro: include_history is not supported.".into());
}
if !prefix.starts_with(&format!("{}::", self.get_user_id()?)) {
return Err("prefix must start with the given user_id".into());
}
let key_name_prefix = &prefix[prefix.find(':').unwrap() + 2..];
let (string_before, macro_type, string_after) = self._parse_macro(key_name_prefix);
let key_list = match macro_type.as_str() {
"redis" => self._read_keys_redis(&string_before, &string_after).await?,
"fs" => self._read_keys_fs(&string_before, &string_after).await?,
_ => {
return Err(format!(
"invalid storage macro, found {} in prefix {}",
macro_type, key_name_prefix
)
.into());
}
};
let mut res: Vec<StorageEntry> = Vec::new();
for key in key_list {
res.push(StorageEntry {
key_name: Default::default(),
key_path: format!("{}:{}@0", prefix, key),
payload: Default::default(),
});
}
Ok(res)
}
}