1use std::{fmt, path::Path};
2
3pub use cortexkit_paths::{IdentityError, ProjectRootId};
4
5#[derive(Clone, Debug, PartialEq, Eq, Hash)]
10pub struct SessionId(String);
11
12impl SessionId {
13 pub fn new(value: impl Into<String>) -> Self {
15 Self(value.into())
16 }
17
18 pub fn as_str(&self) -> &str {
20 &self.0
21 }
22
23 pub fn into_string(self) -> String {
25 self.0
26 }
27}
28
29impl AsRef<str> for SessionId {
30 fn as_ref(&self) -> &str {
31 self.as_str()
32 }
33}
34
35impl fmt::Display for SessionId {
36 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
37 f.write_str(&self.0)
38 }
39}
40
41impl From<&str> for SessionId {
42 fn from(value: &str) -> Self {
43 Self::new(value)
44 }
45}
46
47impl From<String> for SessionId {
48 fn from(value: String) -> Self {
49 Self::new(value)
50 }
51}
52
53impl From<SessionId> for String {
54 fn from(value: SessionId) -> Self {
55 value.into_string()
56 }
57}
58
59#[derive(Clone, Debug, PartialEq, Eq, Hash)]
64pub struct RequestIdentity {
65 pub session_id: SessionId,
66 pub project_root: ProjectRootId,
67}
68
69impl RequestIdentity {
70 pub fn new(session_id: impl Into<SessionId>, project_root: ProjectRootId) -> Self {
71 Self {
72 session_id: session_id.into(),
73 project_root,
74 }
75 }
76
77 pub fn from_path(
78 session_id: impl Into<SessionId>,
79 project_root: impl AsRef<Path>,
80 ) -> Result<Self, IdentityError> {
81 Ok(Self::new(
82 session_id,
83 ProjectRootId::from_path(project_root)?,
84 ))
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use std::{collections::HashMap, fs};
91
92 use super::*;
93 use crate::test_support::TestTempDir as TestDir;
94
95 #[test]
96 fn request_identity_is_hashable_as_hash_map_key() {
97 let temp = TestDir::new("hashmap");
98 let root = temp.path().join("project");
99 fs::create_dir(&root).expect("create project root");
100
101 let identity = RequestIdentity::from_path("ses_a", &root).expect("build request identity");
102 let same_identity = RequestIdentity::from_path(String::from("ses_a"), root.join("."))
103 .expect("build equivalent request identity");
104 let other_session = RequestIdentity::from_path("ses_b", &root)
105 .expect("build different-session request identity");
106
107 let mut entries = HashMap::new();
108 entries.insert(identity.clone(), "session A project state");
109
110 assert_eq!(
111 entries.get(&same_identity),
112 Some(&"session A project state")
113 );
114 assert_eq!(entries.get(&other_session), None);
115 }
116}