Skip to main content

alpine_protocol_sdk/
capabilities.rs

1use std::collections::HashMap;
2
3use alpine::messages::{CapabilitySet, ChannelFormat};
4use alpine::profile::StreamProfile;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7pub enum CapabilityMatchMode {
8    Strict,
9    Lenient,
10}
11
12#[derive(Debug, Clone)]
13pub struct CapabilityValidation {
14    pub warnings: Vec<String>,
15}
16
17#[derive(Debug, Clone, Default)]
18pub struct CapabilityDeprecationRegistry {
19    vendor_extensions: HashMap<String, String>,
20}
21
22impl CapabilityDeprecationRegistry {
23    pub fn new() -> Self {
24        Self {
25            vendor_extensions: HashMap::new(),
26        }
27    }
28
29    pub fn register_vendor_extension(
30        &mut self,
31        name: impl Into<String>,
32        message: impl Into<String>,
33    ) {
34        self.vendor_extensions.insert(name.into(), message.into());
35    }
36
37    pub fn warnings_for(&self, caps: &CapabilitiesSummary) -> Vec<String> {
38        let mut warnings = Vec::new();
39        if let Some(extensions) = caps.vendor_extensions.as_ref() {
40            for (name, msg) in self.vendor_extensions.iter() {
41                if extensions.contains_key(name) {
42                    warnings.push(format!("capability '{}' deprecated: {}", name, msg));
43                }
44            }
45        }
46        warnings
47    }
48}
49
50#[derive(Debug, Clone)]
51pub struct CapabilitiesSummary {
52    pub channel_formats: Vec<ChannelFormat>,
53    pub max_channels: u32,
54    pub grouping_supported: bool,
55    pub streaming_supported: bool,
56    pub encryption_supported: bool,
57    pub vendor_extensions: Option<HashMap<String, serde_json::Value>>,
58}
59
60impl From<&CapabilitySet> for CapabilitiesSummary {
61    fn from(caps: &CapabilitySet) -> Self {
62        Self {
63            channel_formats: caps.channel_formats.clone(),
64            max_channels: caps.max_channels,
65            grouping_supported: caps.grouping_supported,
66            streaming_supported: caps.streaming_supported,
67            encryption_supported: caps.encryption_supported,
68            vendor_extensions: caps.vendor_extensions.clone(),
69        }
70    }
71}
72
73impl CapabilitiesSummary {
74    pub fn supports_format(&self, format: &ChannelFormat) -> bool {
75        self.channel_formats.contains(format)
76    }
77
78    pub fn validate_stream(
79        &self,
80        format: ChannelFormat,
81        channel_count: usize,
82    ) -> Result<(), String> {
83        if !self.streaming_supported {
84            return Err("streaming not supported by device".into());
85        }
86        if !self.supports_format(&format) {
87            return Err(format!("channel format {:?} not supported", format));
88        }
89        if channel_count as u32 > self.max_channels {
90            return Err(format!(
91                "channel count {} exceeds device max {}",
92                channel_count, self.max_channels
93            ));
94        }
95        Ok(())
96    }
97
98    pub fn validate_stream_with_mode(
99        &self,
100        format: ChannelFormat,
101        channel_count: usize,
102        mode: CapabilityMatchMode,
103    ) -> Result<CapabilityValidation, String> {
104        match mode {
105            CapabilityMatchMode::Strict => {
106                self.validate_stream(format, channel_count)?;
107                Ok(CapabilityValidation {
108                    warnings: Vec::new(),
109                })
110            }
111            CapabilityMatchMode::Lenient => {
112                let mut warnings = Vec::new();
113                if !self.streaming_supported {
114                    warnings.push("streaming not supported by device".to_string());
115                }
116                if !self.supports_format(&format) {
117                    warnings.push(format!("channel format {:?} not supported", format));
118                }
119                if channel_count as u32 > self.max_channels {
120                    warnings.push(format!(
121                        "channel count {} exceeds device max {}",
122                        channel_count, self.max_channels
123                    ));
124                }
125                Ok(CapabilityValidation { warnings })
126            }
127        }
128    }
129
130    pub fn deprecation_warnings(&self, registry: &CapabilityDeprecationRegistry) -> Vec<String> {
131        registry.warnings_for(self)
132    }
133
134    pub fn validate_profile(&self, profile: &StreamProfile) -> Result<(), String> {
135        if !self.streaming_supported {
136            return Err("streaming not supported by device".into());
137        }
138        profile
139            .clone()
140            .compile()
141            .map(|_| ())
142            .map_err(|err| err.to_string())
143    }
144}