use std::{
path::PathBuf,
sync::atomic::{AtomicU64, Ordering},
};
use serde::{Deserialize, Serialize};
use sqry_core::project::ProjectRootMode;
pub use sqry_daemon_protocol::protocol::WorkspaceState;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub struct WorkspaceKey {
pub index_root: PathBuf,
pub root_mode: ProjectRootMode,
pub config_fingerprint: u64,
}
impl WorkspaceKey {
#[must_use]
pub fn new(index_root: PathBuf, root_mode: ProjectRootMode, config_fingerprint: u64) -> Self {
Self {
index_root,
root_mode,
config_fingerprint,
}
}
}
impl std::fmt::Display for WorkspaceKey {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}[{}@{:016x}]",
self.index_root.display(),
self.root_mode,
self.config_fingerprint,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct OldGraphToken(u64);
impl OldGraphToken {
pub fn new() -> Self {
static COUNTER: AtomicU64 = AtomicU64::new(1);
Self(COUNTER.fetch_add(1, Ordering::Relaxed))
}
#[must_use]
pub const fn raw(self) -> u64 {
self.0
}
}
impl Default for OldGraphToken {
fn default() -> Self {
Self::new()
}
}
impl std::fmt::Display for OldGraphToken {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "OldGraphToken({})", self.0)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn state_round_trips_via_discriminant() {
for &s in &[
WorkspaceState::Unloaded,
WorkspaceState::Loading,
WorkspaceState::Loaded,
WorkspaceState::Rebuilding,
WorkspaceState::Evicted,
WorkspaceState::Failed,
] {
assert_eq!(WorkspaceState::from_u8(s.as_u8()), Some(s), "{s}");
}
}
#[test]
fn state_from_out_of_range_is_none() {
assert_eq!(WorkspaceState::from_u8(6), None);
assert_eq!(WorkspaceState::from_u8(255), None);
}
#[test]
fn state_is_serving_matches_a2_table() {
assert!(!WorkspaceState::Unloaded.is_serving());
assert!(!WorkspaceState::Loading.is_serving());
assert!(WorkspaceState::Loaded.is_serving());
assert!(WorkspaceState::Rebuilding.is_serving());
assert!(!WorkspaceState::Evicted.is_serving());
assert!(WorkspaceState::Failed.is_serving());
}
#[test]
fn key_distinguishes_root_mode_and_fingerprint() {
let a = WorkspaceKey::new(
PathBuf::from("/repos/example"),
ProjectRootMode::GitRoot,
0x1234_5678_9abc_def0,
);
let b = WorkspaceKey::new(
PathBuf::from("/repos/example"),
ProjectRootMode::WorkspaceFolder,
0x1234_5678_9abc_def0,
);
let c = WorkspaceKey::new(
PathBuf::from("/repos/example"),
ProjectRootMode::GitRoot,
0xdead_beef_dead_beef,
);
assert_ne!(a, b, "different root_mode must be different keys");
assert_ne!(a, c, "different fingerprint must be different keys");
assert_eq!(a, a.clone(), "same components compare equal");
}
#[test]
fn token_is_monotonic_and_unique() {
let a = OldGraphToken::new();
let b = OldGraphToken::new();
let c = OldGraphToken::new();
assert!(a.raw() < b.raw());
assert!(b.raw() < c.raw());
assert_ne!(a, b);
assert_ne!(b, c);
}
}