use super::{DelegatedSessionBootstrapBindingRecord, DelegatedSessionRecord};
use crate::storage::prelude::*;
pub(super) fn get_active_delegated_session(
sessions: &mut Vec<DelegatedSessionRecord>,
wallet_pid: Principal,
now_secs: u64,
) -> Option<DelegatedSessionRecord> {
let delegated = sessions
.iter()
.find(|entry| entry.wallet_pid == wallet_pid)
.copied();
let active = delegated.filter(|entry| !session_expired(entry.expires_at, now_secs));
if active.is_none() {
sessions.retain(|entry| entry.wallet_pid != wallet_pid);
}
active
}
pub(super) fn upsert_delegated_session(
sessions: &mut Vec<DelegatedSessionRecord>,
session: DelegatedSessionRecord,
now_secs: u64,
capacity: usize,
) {
prune_expired_sessions(sessions, now_secs);
if let Some(entry) = sessions
.iter_mut()
.find(|entry| entry.wallet_pid == session.wallet_pid)
{
*entry = session;
} else {
if sessions.len() >= capacity {
evict_oldest_session(sessions);
}
sessions.push(session);
}
}
pub(super) fn clear_delegated_session(
sessions: &mut Vec<DelegatedSessionRecord>,
wallet_pid: Principal,
) {
sessions.retain(|entry| entry.wallet_pid != wallet_pid);
}
pub(super) fn prune_expired_delegated_sessions(
sessions: &mut Vec<DelegatedSessionRecord>,
now_secs: u64,
) -> usize {
let before = sessions.len();
prune_expired_sessions(sessions, now_secs);
before.saturating_sub(sessions.len())
}
pub(super) fn get_active_delegated_session_bootstrap_binding(
bindings: &mut Vec<DelegatedSessionBootstrapBindingRecord>,
token_fingerprint: [u8; 32],
now_secs: u64,
) -> Option<DelegatedSessionBootstrapBindingRecord> {
let binding = bindings
.iter()
.find(|entry| entry.token_fingerprint == token_fingerprint)
.copied();
let active = binding.filter(|entry| !session_binding_expired(entry.expires_at, now_secs));
if active.is_none() {
bindings.retain(|entry| entry.token_fingerprint != token_fingerprint);
}
active
}
pub(super) fn upsert_delegated_session_bootstrap_binding(
bindings: &mut Vec<DelegatedSessionBootstrapBindingRecord>,
binding: DelegatedSessionBootstrapBindingRecord,
now_secs: u64,
capacity: usize,
) {
prune_expired_session_bindings(bindings, now_secs);
if let Some(entry) = bindings
.iter_mut()
.find(|entry| entry.token_fingerprint == binding.token_fingerprint)
{
*entry = binding;
} else {
if bindings.len() >= capacity {
evict_oldest_session_binding(bindings);
}
bindings.push(binding);
}
}
pub(super) fn prune_expired_delegated_session_bootstrap_bindings(
bindings: &mut Vec<DelegatedSessionBootstrapBindingRecord>,
now_secs: u64,
) -> usize {
let before = bindings.len();
prune_expired_session_bindings(bindings, now_secs);
before.saturating_sub(bindings.len())
}
const fn session_expired(expires_at: u64, now_secs: u64) -> bool {
now_secs > expires_at
}
fn prune_expired_sessions(sessions: &mut Vec<DelegatedSessionRecord>, now_secs: u64) {
sessions.retain(|entry| !session_expired(entry.expires_at, now_secs));
}
const fn session_binding_expired(expires_at: u64, now_secs: u64) -> bool {
now_secs > expires_at
}
fn prune_expired_session_bindings(
bindings: &mut Vec<DelegatedSessionBootstrapBindingRecord>,
now_secs: u64,
) {
bindings.retain(|entry| !session_binding_expired(entry.expires_at, now_secs));
}
fn evict_oldest_session(sessions: &mut Vec<DelegatedSessionRecord>) {
if sessions.is_empty() {
return;
}
let mut oldest_index = 0usize;
for (idx, entry) in sessions.iter().enumerate().skip(1) {
let oldest = &sessions[oldest_index];
if (entry.expires_at, entry.issued_at) < (oldest.expires_at, oldest.issued_at) {
oldest_index = idx;
}
}
sessions.swap_remove(oldest_index);
}
fn evict_oldest_session_binding(bindings: &mut Vec<DelegatedSessionBootstrapBindingRecord>) {
if bindings.is_empty() {
return;
}
let mut oldest_index = 0usize;
for (idx, entry) in bindings.iter().enumerate().skip(1) {
let oldest = &bindings[oldest_index];
if (entry.expires_at, entry.bound_at) < (oldest.expires_at, oldest.bound_at) {
oldest_index = idx;
}
}
bindings.swap_remove(oldest_index);
}