trading_ig/session/
mod.rs1use std::sync::Arc;
8
9use serde::{Deserialize, Serialize};
10use tokio::sync::RwLock;
11
12use crate::client::http::Transport;
13use crate::error::{Error, Result};
14
15mod auth;
16#[cfg(feature = "encryption")]
17pub mod encryption;
18mod tokens;
19
20pub use auth::{SessionApi, SessionDetails, SwitchAccountResponse};
21pub use tokens::{AuthTokens, SessionState};
22
23#[derive(Debug, Clone)]
25pub enum Credentials {
26 Password { username: String, password: String },
28}
29
30impl Credentials {
31 pub fn password(username: impl Into<String>, password: impl Into<String>) -> Self {
32 Self::Password {
33 username: username.into(),
34 password: password.into(),
35 }
36 }
37}
38
39#[derive(Debug, Clone, Serialize, Deserialize)]
41#[serde(rename_all = "camelCase")]
42pub struct SessionInfo {
43 pub account_id: String,
44 pub client_id: String,
45 pub timezone_offset: Option<i32>,
46 pub lightstreamer_endpoint: String,
47 pub currency_iso_code: Option<String>,
48 pub locale: Option<String>,
49}
50
51#[derive(Debug, Clone, Default)]
53pub struct SharedSession {
54 inner: Arc<RwLock<SessionState>>,
55}
56
57impl SharedSession {
58 pub async fn snapshot(&self) -> SessionState {
59 self.inner.read().await.clone()
60 }
61
62 pub(crate) async fn replace(&self, new: SessionState) {
63 *self.inner.write().await = new;
64 }
65
66 pub(crate) async fn modify<F>(&self, f: F)
67 where
68 F: FnOnce(&mut SessionState),
69 {
70 let mut guard = self.inner.write().await;
71 f(&mut guard);
72 }
73
74 pub async fn require_authenticated(&self) -> Result<SessionState> {
75 let s = self.snapshot().await;
76 if s.tokens.is_some() {
77 Ok(s)
78 } else {
79 Err(Error::Auth(
80 "no active session — call session().login() first".into(),
81 ))
82 }
83 }
84}
85
86#[derive(Debug, Clone)]
88pub(crate) struct SessionHandle {
89 pub(crate) transport: Transport,
90 pub(crate) session: SharedSession,
91 pub(crate) credentials: Option<Credentials>,
92}
93
94impl SessionHandle {
95 #[cfg(feature = "stream")]
98 pub(crate) fn session_api(&self) -> SessionApi {
99 SessionApi {
100 handle: self.clone(),
101 }
102 }
103}