futu_mcp/state/push_subscribers/
visibility.rs1use 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}