use std::fmt;
use serde::{Deserialize, Serialize};
#[derive(
Debug,
Clone,
Copy,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
zerompk::ToMessagePack,
zerompk::FromMessagePack,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
pub struct TenantId(u32);
impl TenantId {
pub const fn new(id: u32) -> Self {
Self(id)
}
pub const fn as_u32(self) -> u32 {
self.0
}
}
impl fmt::Display for TenantId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "tenant:{}", self.0)
}
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
pub struct CollectionId(String);
impl CollectionId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for CollectionId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
pub struct DocumentId(String);
impl DocumentId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for DocumentId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
pub struct NodeId(String);
impl NodeId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for NodeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
pub struct EdgeId(String);
impl EdgeId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn from_components(src: &str, dst: &str, label: &str) -> Self {
Self(format!("{src}--{label}-->{dst}"))
}
}
impl fmt::Display for EdgeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
#[derive(
Debug,
Clone,
PartialEq,
Eq,
Hash,
Serialize,
Deserialize,
rkyv::Archive,
rkyv::Serialize,
rkyv::Deserialize,
)]
pub struct ShapeId(String);
impl ShapeId {
pub fn new(id: impl Into<String>) -> Self {
Self(id.into())
}
pub fn as_str(&self) -> &str {
&self.0
}
}
impl fmt::Display for ShapeId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(&self.0)
}
}
impl From<String> for ShapeId {
fn from(s: String) -> Self {
Self(s)
}
}
impl From<&str> for ShapeId {
fn from(s: &str) -> Self {
Self(s.to_owned())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn tenant_id_display() {
let t = TenantId::new(42);
assert_eq!(t.to_string(), "tenant:42");
assert_eq!(t.as_u32(), 42);
}
#[test]
fn collection_id() {
let c = CollectionId::new("embeddings");
assert_eq!(c.as_str(), "embeddings");
assert_eq!(c.to_string(), "embeddings");
}
#[test]
fn document_id_str() {
let d = DocumentId::new("doc-abc-123");
assert_eq!(d.as_str(), "doc-abc-123");
}
#[test]
fn node_id() {
let n = NodeId::new("concept:rust");
assert_eq!(n.as_str(), "concept:rust");
}
#[test]
fn edge_id_from_components() {
let e = EdgeId::from_components("alice", "bob", "KNOWS");
assert_eq!(e.as_str(), "alice--KNOWS-->bob");
}
#[test]
fn shape_id_from_str() {
let s = ShapeId::from("shape-001");
assert_eq!(s.as_str(), "shape-001");
}
#[test]
fn serde_roundtrip() {
let tid = TenantId::new(7);
let json = sonic_rs::to_string(&tid).unwrap();
let decoded: TenantId = sonic_rs::from_str(&json).unwrap();
assert_eq!(tid, decoded);
}
}