cosmwasm_vm/
capabilities.rs1use std::collections::HashSet;
2
3use crate::static_analysis::ExportInfo;
4
5const REQUIRES_PREFIX: &str = "requires_";
6
7pub fn capabilities_from_csv(csv: &str) -> HashSet<String> {
10 csv.split(',')
11 .map(|x| x.trim().to_string())
12 .filter(|f| !f.is_empty())
13 .collect()
14}
15
16pub fn required_capabilities_from_module(module: impl ExportInfo) -> HashSet<String> {
19 module
20 .exported_function_names(Some(REQUIRES_PREFIX))
21 .into_iter()
22 .filter_map(|name| {
23 if name.len() > REQUIRES_PREFIX.len() {
24 let (_, required_capability) = name.split_at(REQUIRES_PREFIX.len());
25 Some(required_capability.to_string())
26 } else {
27 None
28 }
29 })
30 .collect()
31}
32
33#[cfg(test)]
34mod tests {
35 use crate::parsed_wasm::ParsedWasm;
36
37 use super::*;
38
39 #[test]
40 fn capabilities_from_csv_works() {
41 let set = capabilities_from_csv("foo, bar,baz ");
42 assert_eq!(set.len(), 3);
43 assert!(set.contains("foo"));
44 assert!(set.contains("bar"));
45 assert!(set.contains("baz"));
46 }
47
48 #[test]
49 fn capabilities_from_csv_skips_empty() {
50 let set = capabilities_from_csv("");
51 assert_eq!(set.len(), 0);
52 let set = capabilities_from_csv("a,,b");
53 assert_eq!(set.len(), 2);
54 assert!(set.contains("a"));
55 assert!(set.contains("b"));
56 let set = capabilities_from_csv("a,b,");
57 assert_eq!(set.len(), 2);
58 assert!(set.contains("a"));
59 assert!(set.contains("b"));
60 }
61
62 #[test]
63 fn required_capabilities_from_module_works() {
64 let wasm = wat::parse_str(
65 r#"(module
66 (type (func))
67 (func (type 0) nop)
68 (export "requires_water" (func 0))
69 (export "requires_" (func 0))
70 (export "requires_nutrients" (func 0))
71 (export "require_milk" (func 0))
72 (export "REQUIRES_air" (func 0))
73 (export "requires_sun" (func 0))
74 )"#,
75 )
76 .unwrap();
77 let module = ParsedWasm::parse(&wasm).unwrap();
78
79 let required_capabilities = required_capabilities_from_module(&module);
80 assert_eq!(required_capabilities.len(), 3);
81 assert!(required_capabilities.contains("nutrients"));
82 assert!(required_capabilities.contains("sun"));
83 assert!(required_capabilities.contains("water"));
84 }
85
86 #[test]
87 fn required_capabilities_from_module_works_without_exports_section() {
88 let wasm = wat::parse_str(r#"(module)"#).unwrap();
89 let module = ParsedWasm::parse(&wasm).unwrap();
90 let required_capabilities = required_capabilities_from_module(&module);
91 assert_eq!(required_capabilities.len(), 0);
92 }
93}