vtcode_commons/
history_scope.rs1use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
11#[serde(rename_all = "lowercase")]
12pub enum HistoryScope {
13 #[default]
15 Everywhere,
16 Project,
18 Session,
20}
21
22impl HistoryScope {
23 #[must_use]
25 pub fn label(self) -> &'static str {
26 match self {
27 Self::Everywhere => "everywhere",
28 Self::Project => "project",
29 Self::Session => "session",
30 }
31 }
32
33 #[must_use]
36 pub fn title(self) -> &'static str {
37 match self {
38 Self::Everywhere => "Everywhere",
39 Self::Project => "Project",
40 Self::Session => "Session",
41 }
42 }
43
44 #[must_use]
46 pub fn cycle_next(self) -> Self {
47 match self {
48 Self::Everywhere => Self::Project,
49 Self::Project => Self::Session,
50 Self::Session => Self::Everywhere,
51 }
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use super::*;
58
59 #[test]
60 fn cycle_runs_broad_to_narrow_and_wraps() {
61 assert_eq!(HistoryScope::Everywhere.cycle_next(), HistoryScope::Project);
62 assert_eq!(HistoryScope::Project.cycle_next(), HistoryScope::Session);
63 assert_eq!(HistoryScope::Session.cycle_next(), HistoryScope::Everywhere);
64 }
65
66 #[test]
67 fn labels_match_wire_values() {
68 for scope in [HistoryScope::Everywhere, HistoryScope::Project, HistoryScope::Session] {
69 let encoded = serde_json::to_value(scope).expect("scope serializes");
70 assert_eq!(encoded, serde_json::Value::String(scope.label().to_string()));
71 let decoded: HistoryScope = serde_json::from_value(encoded).expect("scope deserializes");
72 assert_eq!(decoded, scope);
73 }
74 assert_eq!(HistoryScope::Everywhere.title(), "Everywhere");
75 assert_eq!(HistoryScope::Project.title(), "Project");
76 assert_eq!(HistoryScope::Session.title(), "Session");
77 }
78
79 #[test]
80 fn unknown_wire_values_reject() {
81 for raw in ["", "EventEverywhere", "workspace", "galaxy"] {
82 assert!(
83 serde_json::from_value::<HistoryScope>(serde_json::Value::String(raw.to_string())).is_err(),
84 "{raw:?} must not parse as a scope"
85 );
86 }
87 }
88}