primitives/types/identifiers/
session_id.rs1use aes::cipher::generic_array::GenericArray;
2use derive_more::derive::{AsMut, AsRef, IntoIterator};
3use hybrid_array::Array;
4#[cfg(any(test, feature = "dev"))]
5use rand::{distributions::Standard, prelude::Distribution, Rng};
6use serde::{Deserialize, Serialize};
7#[cfg(any(test, feature = "dev"))]
8use typenum::Unsigned;
9use typenum::U16;
10use wincode::{SchemaRead, SchemaWrite};
11
12use crate::{
13 constants::CollisionResistanceBytes,
14 hashing::{self, Digest},
15 random::Seed,
16 transcripts::Transcript,
17};
18
19#[derive(
25 Default,
26 Copy,
27 AsRef,
28 AsMut,
29 Clone,
30 Serialize,
31 Deserialize,
32 SchemaRead,
33 SchemaWrite,
34 PartialEq,
35 IntoIterator,
36)]
37#[into_iterator(owned, ref, ref_mut)]
38#[repr(transparent)]
39pub struct SessionId(Array<u8, CollisionResistanceBytes>);
40
41impl SessionId {
42 pub fn refresh_with<T: AsRef<[u8]> + ?Sized>(&mut self, tag: &T) {
44 self.0 = hashing::hash(&[self.as_ref(), tag.as_ref()]);
45 }
46
47 pub fn refresh_from<T: Transcript>(transcript: &mut T) -> SessionId {
49 SessionId(transcript.extract(b"new_session_id").into())
50 }
51}
52
53impl AsRef<[u8]> for SessionId {
56 fn as_ref(&self) -> &[u8] {
57 &self.0
58 }
59}
60
61impl std::ops::Deref for SessionId {
62 type Target = [u8; 32];
63
64 fn deref(&self) -> &[u8; 32] {
65 self.0.as_ref()
66 }
67}
68
69impl From<Digest> for SessionId {
70 fn from(value: Digest) -> Self {
71 SessionId(value)
72 }
73}
74
75impl From<SessionId> for [u8; 32] {
76 fn from(session_id: SessionId) -> [u8; 32] {
77 session_id.0.into()
78 }
79}
80
81impl<'sid> From<&'sid SessionId> for &'sid [u8; 32] {
82 fn from(session_id: &'sid SessionId) -> &'sid [u8; 32] {
83 (&session_id.0).into()
84 }
85}
86
87impl From<&SessionId> for u32 {
88 fn from(session_id: &SessionId) -> u32 {
89 u32::from_le_bytes(session_id.0[0..4].try_into().unwrap())
90 }
91}
92
93impl From<&SessionId> for [u8; 16] {
94 fn from(session_id: &SessionId) -> [u8; 16] {
95 let mut hash = [0; 16];
96 hashing::hash_into([session_id], &mut hash);
97 hash
98 }
99}
100
101impl From<&SessionId> for GenericArray<u8, U16> {
102 fn from(session_id: &SessionId) -> GenericArray<u8, U16> {
103 let mut hash = GenericArray::<u8, U16>::default();
104 hashing::hash_into([session_id], &mut hash);
105 hash
106 }
107}
108
109pub trait SessionIdGenerator {
115 fn generate_session_id_from(&self, seed: Seed) -> SessionId {
117 SessionId(seed.into())
118 }
119}
120
121#[cfg(any(test, feature = "dev"))]
122impl Distribution<SessionId> for Standard {
123 fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> SessionId {
124 let mut bytes = Array([0; CollisionResistanceBytes::USIZE]);
125 rng.fill_bytes(&mut bytes);
126 SessionId(bytes)
127 }
128}
129
130#[cfg(any(test, feature = "dev"))]
131impl SessionId {
132 pub fn from_hashed_seed(seed: &[u8]) -> SessionId {
134 let mut bytes = Array([0; CollisionResistanceBytes::USIZE]);
135 hashing::hash_into([seed], &mut bytes);
136 SessionId(bytes)
137 }
138}
139
140#[cfg(not(any(test, feature = "dev")))]
143impl std::fmt::Display for SessionId {
144 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
145 write!(f, "SessionId({})", hex::encode(self.0))
146 }
147}
148
149#[cfg(not(any(test, feature = "dev")))]
150impl std::fmt::Debug for SessionId {
151 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
152 write!(f, "SessionId({})", hex::encode(self.0))
153 }
154}
155
156#[cfg(any(test, feature = "dev"))]
157impl std::fmt::Display for SessionId {
158 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
159 write!(f, "SessionId({}...)", &hex::encode(self.0)[0..6])
160 }
161}
162
163#[cfg(any(test, feature = "dev"))]
164impl std::fmt::Debug for SessionId {
165 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
166 write!(f, "SessionId({}...)", &hex::encode(self.0)[0..6])
167 }
168}