use std::collections::BTreeMap;
use std::fmt;
use serde::{Deserialize, Serialize};
use serde_json::Value;
use uuid::Uuid;
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(transparent)]
pub struct WorkspaceId(Uuid);
impl WorkspaceId {
pub fn new() -> Self {
Self(Uuid::now_v7())
}
pub fn parse(input: &str) -> Result<Self, uuid::Error> {
Uuid::parse_str(input).map(Self)
}
}
impl Default for WorkspaceId {
fn default() -> Self {
Self::new()
}
}
impl fmt::Display for WorkspaceId {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
#[serde(transparent)]
pub struct NodeId(Uuid);
impl NodeId {
pub fn new() -> Self {
Self(Uuid::now_v7())
}
pub fn parse(input: &str) -> Result<Self, uuid::Error> {
Uuid::parse_str(input).map(Self)
}
}
impl Default for NodeId {
fn default() -> Self {
Self::new()
}
}
impl fmt::Display for NodeId {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(formatter)
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, Ord, PartialEq, PartialOrd, Serialize)]
#[serde(transparent)]
pub struct Revision(u64);
impl Revision {
pub const INITIAL: Self = Self(1);
pub const fn new(value: u64) -> Option<Self> {
if value == 0 { None } else { Some(Self(value)) }
}
pub const fn next(self) -> Self {
match self.0.checked_add(1) {
Some(value) => Self(value),
None => panic!("revision overflow"),
}
}
pub const fn get(self) -> u64 {
self.0
}
}
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum NodeKind {
Directory,
File,
Symlink,
}
#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
pub struct Node {
pub workspace_id: WorkspaceId,
pub id: NodeId,
pub parent_id: Option<NodeId>,
pub name: String,
pub kind: NodeKind,
pub logical_size: u64,
pub created_at_ms: i64,
pub modified_at_ms: i64,
pub accessed_at_ms: i64,
pub revision: Revision,
pub attributes: BTreeMap<String, Value>,
}