104 lines
2.7 KiB
Rust
Raw Normal View History

use serde::Serialize;
use serde::de::DeserializeOwned;
use sqlx::SqlitePool;
use crate::errors::*;
pub async fn save<T>(pool: &SqlitePool, name: &str, value: &T) -> Result<(), sqlx::Error>
where T: Serialize
{
let bytes = serde_json::to_vec(value).unwrap();
save_bytes(pool, name, &bytes).await
}
pub async fn save_bytes(pool: &SqlitePool, name: &str, bytes: &[u8]) -> Result<(), sqlx::Error> {
sqlx::query!(
"INSERT INTO kv (name, value) VALUES (?, ?)
ON CONFLICT(name) DO UPDATE SET value = excluded.value;",
name,
bytes,
).execute(pool).await?;
Ok(())
}
pub async fn load<T>(pool: &SqlitePool, name: &str) -> Result<Option<T>, LoadKvError>
where T: DeserializeOwned
{
let v = load_bytes(pool, name)
.await?
.map(|bytes| serde_json::from_slice(&bytes))
.transpose()?;
Ok(v)
}
pub async fn load_bytes(pool: &SqlitePool, name: &str) -> Result<Option<Vec<u8>>, sqlx::Error> {
sqlx::query!("SELECT name, value FROM kv WHERE name = ?", name)
.map(|row| row.value)
.fetch_optional(pool)
.await
.map(|o| o.flatten())
}
// pub async fn load_bytes_multi<const N: usize>(
// pool: &SqlitePool,
// names: [&str; N],
// ) -> Result<Option<[Vec<u8>; N]>, sqlx::Error> {
// // just use multiple queries, who cares
// let res: [Vec<u8>; N] = Default::default();
// for (i, name) in names.as_slice().iter().enumerate() {
// match load_bytes(pool, name).await? {
// Some(bytes) => res[i] = bytes,
// None => return Ok(None),
// }
// }
// Ok(res);
// }
macro_rules! load_bytes_multi {
(
$pool:ident,
$($name:literal),*
) => {
// wrap everything up in an immediately-invoked closure for easy short-circuiting
(|| {
// a tuple, with one item for each repetition of $name
(
// repeat this match block for every name
$(
// load_bytes returns Result<Option<_>>, the Result is handled by
// the ? and we match on the Option
match load_bytes(pool, $name)? {
Some(v) => v,
None => return Ok(None)
},
)*
)
})()
}
}
// macro_rules! load_multi {
// (
// $pool:ident,
// $($name:literal),*
// ) => {
// (|| {
// (
// $(
// match load(pool, $name)? {
// Some(v) => v,
// None => return Ok(None)
// },
// )*
// )
// })()
// }
// }