1use pkarr::PublicKey;
4use postcard::{from_bytes, to_allocvec};
5use serde::{Deserialize, Serialize};
6
7extern crate alloc;
8use alloc::vec::Vec;
9
10use crate::{capabilities::Capability, timestamp::Timestamp};
11
12#[derive(Clone, Serialize, Deserialize, Debug, Eq, PartialEq)]
16pub struct Session {
18 version: usize,
19 pubky: PublicKey,
20 created_at: u64,
21 name: String,
23 user_agent: String,
24 capabilities: Vec<Capability>,
25}
26
27impl Session {
28 pub fn new(pubky: &PublicKey, capabilities: &[Capability], user_agent: Option<String>) -> Self {
30 Self {
31 version: 0,
32 pubky: pubky.clone(),
33 created_at: Timestamp::now().as_u64(),
34 capabilities: capabilities.to_vec(),
35 user_agent: user_agent.as_deref().unwrap_or("").to_string(),
36 name: user_agent.as_deref().unwrap_or("").to_string(),
37 }
38 }
39
40 pub fn pubky(&self) -> &PublicKey {
44 &self.pubky
45 }
46
47 pub fn capabilities(&self) -> &Vec<Capability> {
49 &self.capabilities
50 }
51
52 pub fn set_user_agent(&mut self, user_agent: String) -> &mut Self {
56 self.user_agent = user_agent;
57
58 if self.name.is_empty() {
59 self.name.clone_from(&self.user_agent)
60 }
61
62 self
63 }
64
65 pub fn set_capabilities(&mut self, capabilities: Vec<Capability>) -> &mut Self {
67 self.capabilities = capabilities;
68
69 self
70 }
71
72 pub fn serialize(&self) -> Vec<u8> {
76 to_allocvec(self).expect("Session::serialize")
77 }
78
79 pub fn deserialize(bytes: &[u8]) -> Result<Self, Error> {
81 if bytes.is_empty() {
82 return Err(Error::EmptyPayload);
83 }
84
85 if bytes[0] > 0 {
86 return Err(Error::UnknownVersion);
87 }
88
89 Ok(from_bytes(bytes)?)
90 }
91
92 }
94
95#[derive(thiserror::Error, Debug, PartialEq)]
96pub enum Error {
98 #[error("Empty payload")]
99 EmptyPayload,
101 #[error("Unknown version")]
102 UnknownVersion,
104 #[error(transparent)]
105 Parsing(#[from] postcard::Error),
107}
108
109#[cfg(test)]
110mod tests {
111 use crate::crypto::Keypair;
112
113 use super::*;
114
115 #[test]
116 fn serialize() {
117 let keypair = Keypair::from_secret_key(&[0; 32]);
118 let pubky = keypair.public_key();
119
120 let session = Session {
121 user_agent: "foo".to_string(),
122 capabilities: vec![Capability::root()],
123 created_at: 0,
124 pubky,
125 version: 0,
126 name: "".to_string(),
127 };
128
129 let serialized = session.serialize();
130
131 assert_eq!(
132 serialized,
133 [
134 0, 59, 106, 39, 188, 206, 182, 164, 45, 98, 163, 168, 208, 42, 111, 13, 115, 101,
135 50, 21, 119, 29, 226, 67, 166, 58, 192, 72, 161, 139, 89, 218, 41, 0, 0, 3, 102,
136 111, 111, 1, 4, 47, 58, 114, 119
137 ]
138 );
139
140 let deseiralized = Session::deserialize(&serialized).unwrap();
141
142 assert_eq!(deseiralized, session)
143 }
144
145 #[test]
146 fn deserialize() {
147 let result = Session::deserialize(&[]);
148
149 assert_eq!(result, Err(Error::EmptyPayload));
150 }
151}