made_api/
api_capabilities.rs1use std::collections::BTreeSet;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
12pub struct ApiCapabilities {
13 contract_version: u32,
14 library_version: String,
15 capabilities: BTreeSet<String>,
16}
17
18impl ApiCapabilities {
19 #[must_use]
20 pub fn new(
21 contract_version: u32,
22 library_version: impl Into<String>,
23 capabilities: impl IntoIterator<Item = impl Into<String>>,
24 ) -> Self {
25 Self {
26 contract_version,
27 library_version: library_version.into(),
28 capabilities: capabilities.into_iter().map(Into::into).collect(),
29 }
30 }
31
32 #[must_use]
33 pub fn contract_version(&self) -> u32 {
34 self.contract_version
35 }
36
37 #[must_use]
38 pub fn library_version(&self) -> &str {
39 &self.library_version
40 }
41
42 #[must_use]
43 pub fn supports(&self, capability: &str) -> bool {
44 self.capabilities.contains(capability)
45 }
46
47 pub fn capabilities(&self) -> impl Iterator<Item = &str> {
48 self.capabilities.iter().map(String::as_str)
49 }
50}
51
52#[cfg(test)]
53mod tests {
54 use super::*;
55
56 #[test]
57 fn a_report_names_its_contract_its_release_and_what_it_can_do() {
58 let report = ApiCapabilities::new(1, "0.1.0", ["list_ceremonies", "get_ceremony"]);
59 assert_eq!(report.contract_version(), 1);
60 assert_eq!(report.library_version(), "0.1.0");
61 assert!(report.supports("list_ceremonies"));
62 assert!(
63 !report.supports("promote_pattern"),
64 "a capability nobody declared must read as absent, not assumed"
65 );
66 }
67
68 #[test]
69 fn a_report_survives_the_wire() {
70 let report = ApiCapabilities::new(1, "0.1.0", ["get_ceremony"]);
71 let bytes = serde_json::to_vec(&report).expect("serializes");
72 assert_eq!(
73 serde_json::from_slice::<ApiCapabilities>(&bytes).expect("deserializes"),
74 report
75 );
76 }
77}