use crate::{MemoryCandidate, MemoryKey, MemoryRecord};
use const_format::concatcp;
use serde::{Deserialize, Serialize};
pub const NAMESPACE_HEADER: &str = "x-tact-memory-namespace";
pub const MAX_NAMESPACE_BYTES: usize = 128;
pub const BOOKMARK_HEADER: &str = "x-tact-memory-bookmark";
pub const MAX_BOOKMARK_BYTES: usize = 4 * 1024;
pub const SESSION_PATH: &str = concatcp!("v", crate::VERSION, "/session");
pub const SCAN_PATH: &str = concatcp!("v", crate::VERSION, "/memories/scan");
pub const READ_PATH: &str = concatcp!("v", crate::VERSION, "/memories/read");
pub const LIST_PATH: &str = concatcp!("v", crate::VERSION, "/memories/list");
pub const PUT_PATH: &str = concatcp!("v", crate::VERSION, "/memories/put");
pub const DELETE_PATH: &str = concatcp!("v", crate::VERSION, "/memories/delete");
pub const SYNC_PATH: &str = concatcp!("v", crate::VERSION, "/memories/sync");
pub const EXPORT_PATH: &str = concatcp!("v", crate::VERSION, "/memories/export");
pub const MAX_EXPORT_PAGE_RECORDS: usize = 128;
pub fn is_valid_namespace(namespace: &str) -> bool {
!namespace.is_empty()
&& namespace.len() <= MAX_NAMESPACE_BYTES
&& namespace
.bytes()
.all(|byte| byte.is_ascii_alphanumeric() || matches!(byte, b'-' | b'_' | b'.'))
}
pub fn is_valid_bookmark(bookmark: &str) -> bool {
!bookmark.is_empty() && bookmark.len() <= MAX_BOOKMARK_BYTES
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RemoteRole {
Reader,
Writer,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct SessionResponse {
pub protocol_version: u32,
pub namespace: String,
pub role: RemoteRole,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ScanRequest {
pub query: String,
pub limit: usize,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ScanResponse {
pub candidates: Vec<MemoryCandidate>,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ReadRequest {
#[serde(default)]
pub ids: Vec<i64>,
#[serde(default)]
pub keys: Vec<MemoryKey>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ReadResponse {
pub memories: Vec<MemoryRecord>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ListResponse {
pub memories: Vec<MemoryRecord>,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct PutRequest {
pub content: String,
#[serde(default)]
pub replacement: Option<MemoryKey>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct PutResponse {
pub memory: MemoryRecord,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct DeleteRequest {
pub key: MemoryKey,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct SyncRequest {
pub memories: Vec<MemoryRecord>,
}
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ExportCursor {
pub namespace: String,
pub id: i64,
}
#[derive(Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct ExportRequest {
pub namespaces: Option<Vec<String>>,
#[serde(default)]
pub cursor: Option<ExportCursor>,
pub limit: usize,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ExportResponse {
pub memories: Vec<MemoryRecord>,
pub next_cursor: Option<ExportCursor>,
}
#[derive(Clone, Copy, Debug, Default, Deserialize, Eq, PartialEq, Serialize)]
pub struct SyncReport {
pub inserted: usize,
pub replaced: usize,
pub unchanged: usize,
pub deleted: usize,
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum RemoteErrorCode {
BadRequest,
Unauthorized,
Forbidden,
NamespaceMismatch,
UnsupportedProtocol,
QueryTooLarge,
ContentTooLarge,
RecordCapacity,
ContentCapacity,
Duplicate,
NotFound,
Conflict,
Unavailable,
Internal,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorResponse {
pub code: RemoteErrorCode,
}