Skip to main content

grammers_session/storages/
memory.rs

1// Copyright 2020 - developers of the `grammers` project.
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9use std::sync::Mutex;
10
11use futures_core::future::BoxFuture;
12
13use crate::types::{ChannelState, DcOption, PeerId, PeerInfo, UpdateState, UpdatesState};
14use crate::{Session, SessionData};
15
16/// In-memory session interface.
17///
18/// Does not actually offer direct ways to persist the state anywhere,
19/// so it should only be used in very few select cases.
20///
21/// Logging in has a very high cost in terms of flood wait errors,
22/// so the state really should be persisted by other means.
23#[derive(Default)]
24pub struct MemorySession(Mutex<SessionData>);
25
26impl From<SessionData> for MemorySession {
27    /// Constructs a memory session from the entirety of the session data,
28    /// unlike the blanket `From` implementation which cannot import all values
29    fn from(session_data: SessionData) -> Self {
30        Self(Mutex::new(session_data))
31    }
32}
33
34impl Session for MemorySession {
35    fn home_dc_id(&self) -> i32 {
36        self.0.lock().unwrap().home_dc
37    }
38
39    fn set_home_dc_id(&self, dc_id: i32) -> BoxFuture<'_, ()> {
40        Box::pin(async move {
41            self.0.lock().unwrap().home_dc = dc_id;
42        })
43    }
44
45    fn dc_option(&self, dc_id: i32) -> Option<DcOption> {
46        self.0.lock().unwrap().dc_options.get(&dc_id).cloned()
47    }
48
49    fn set_dc_option(&self, dc_option: &DcOption) -> BoxFuture<'_, ()> {
50        let dc_option = dc_option.clone();
51        Box::pin(async move {
52            self.0
53                .lock()
54                .unwrap()
55                .dc_options
56                .insert(dc_option.id, dc_option.clone());
57        })
58    }
59
60    fn peer(&self, peer: PeerId) -> BoxFuture<'_, Option<PeerInfo>> {
61        Box::pin(async move { self.0.lock().unwrap().peer_infos.get(&peer).cloned() })
62    }
63
64    fn cache_peer(&self, peer: &PeerInfo) -> BoxFuture<'_, ()> {
65        let peer = peer.clone();
66        Box::pin(async move {
67            self.0
68                .lock()
69                .unwrap()
70                .peer_infos
71                .insert(peer.id(), peer.clone());
72        })
73    }
74
75    fn updates_state(&self) -> BoxFuture<'_, UpdatesState> {
76        Box::pin(async move { self.0.lock().unwrap().updates_state.clone() })
77    }
78
79    fn set_update_state(&self, update: UpdateState) -> BoxFuture<'_, ()> {
80        Box::pin(async move {
81            let mut data = self.0.lock().unwrap();
82
83            match update {
84                UpdateState::All(updates_state) => {
85                    data.updates_state = updates_state;
86                }
87                UpdateState::Primary { pts, date, seq } => {
88                    data.updates_state.pts = pts;
89                    data.updates_state.date = date;
90                    data.updates_state.seq = seq;
91                }
92                UpdateState::Secondary { qts } => {
93                    data.updates_state.qts = qts;
94                }
95                UpdateState::Channel { id, pts } => {
96                    data.updates_state.channels.retain(|c| c.id != id);
97                    data.updates_state.channels.push(ChannelState { id, pts });
98                }
99            }
100        })
101    }
102}