Skip to main content

futu_mcp/state/push_subscribers/
visibility.rs

1use super::*;
2
3pub(crate) fn push_resource_uri(handle: &str) -> String {
4    format!("{PUSH_RESOURCE_PREFIX}{handle}")
5}
6
7pub(crate) fn parse_push_resource_uri(uri: &str) -> Option<&str> {
8    let handle = uri.strip_prefix(PUSH_RESOURCE_PREFIX)?;
9    let suffix = handle.strip_prefix("sub-")?;
10    (!suffix.is_empty()
11        && suffix.bytes().all(|byte| byte.is_ascii_digit())
12        && push_resource_uri(handle) == uri)
13        .then_some(handle)
14}
15
16fn restricted_set_covers<T: Eq + std::hash::Hash>(
17    registered: Option<&HashSet<T>>,
18    current: Option<&HashSet<T>>,
19) -> bool {
20    match current {
21        None => true,
22        Some(current) if current.is_empty() => true,
23        Some(current) => match registered {
24            None => false,
25            Some(registered) if registered.is_empty() => false,
26            Some(registered) => registered.is_subset(current),
27        },
28    }
29}
30
31pub(super) fn current_scope_allows_subscriber(
32    subscriber: &PushSubscriber,
33    caller_allowed_acc_ids: Option<&HashSet<u64>>,
34    caller_allowed_markets: Option<&HashSet<String>>,
35) -> bool {
36    let accounts_allowed = caller_allowed_acc_ids.is_none_or(|allowed| {
37        allowed.is_empty()
38            || subscriber
39                .acc_ids
40                .iter()
41                .all(|acc_id| allowed.contains(acc_id))
42    });
43    accounts_allowed
44        && restricted_set_covers(
45            subscriber.allowed_markets_snapshot.as_ref(),
46            caller_allowed_markets,
47        )
48}