1use std::ptr::null_mut;
2
3use crate::object::{AsRawMutObject, WafArray, WafMap, WafOwnedDefaultAllocator};
4use crate::{Config, Handle};
5
6#[repr(transparent)]
12pub struct Builder {
13 raw: libddwaf_sys::ddwaf_builder,
14}
15impl Builder {
16 const OBFUSCATOR_KEY: &str = "datadog/0/ASM_DD/0/config";
17
18 #[must_use]
21 pub fn new(config: Option<&Config>) -> Option<Self> {
22 let mut builder = Builder {
23 raw: unsafe { libddwaf_sys::ddwaf_builder_init() },
24 };
25 if builder.raw.is_null() {
26 return None;
27 }
28
29 if let Some(config) = config {
30 let config_obj = config.as_waf_object();
31 let res = builder.add_or_update_config(Self::OBFUSCATOR_KEY, &config_obj, None);
32 if !res {
33 debug_assert!(false, "Failed to add or update obfuscator config");
34 return None;
35 }
36 }
37
38 Some(builder)
39 }
40
41 #[must_use]
49 pub fn add_or_update_config(
50 &mut self,
51 path: &str,
52 ruleset: &impl AsRef<libddwaf_sys::ddwaf_object>,
53 mut diagnostics: Option<&mut WafOwnedDefaultAllocator<WafMap>>,
54 ) -> bool {
55 debug_assert!(
56 !path.is_empty(),
57 concat!(
58 "path cannot be empty (",
59 stringify!(bindings::ddwaf_builder_add_or_update_config),
60 " would always fail)"
61 )
62 );
63 let path_len = u32::try_from(path.len()).expect("path is too long");
64 if let Some(ref mut diagnostics) = diagnostics {
65 let _ = std::mem::take(*diagnostics);
67 }
68 unsafe {
69 libddwaf_sys::ddwaf_builder_add_or_update_config(
70 self.raw,
71 path.as_ptr().cast(),
72 path_len,
73 ruleset.as_ref(),
74 diagnostics.map_or(null_mut(), |o| std::ptr::from_mut(o.as_raw_mut()).cast()),
75 )
76 }
77 }
78
79 pub fn remove_config(&mut self, path: &str) -> bool {
86 let path_len = u32::try_from(path.len()).expect("path is too long");
87 unsafe {
88 libddwaf_sys::ddwaf_builder_remove_config(self.raw, path.as_ptr().cast(), path_len)
89 }
90 }
91
92 #[must_use]
98 pub fn config_paths_count(&mut self, filter: Option<&'_ str>) -> u32 {
99 let filter = filter.unwrap_or("");
100 let filter_len = u32::try_from(filter.len()).expect("filter is too long");
101 unsafe {
102 libddwaf_sys::ddwaf_builder_get_config_paths(
103 self.raw,
104 null_mut(),
105 filter.as_ptr().cast(),
106 filter_len,
107 )
108 }
109 }
110
111 #[must_use]
117 pub fn config_paths(&mut self, filter: Option<&'_ str>) -> WafOwnedDefaultAllocator<WafArray> {
118 let mut res = WafOwnedDefaultAllocator::<WafArray>::default();
120 let filter = filter.unwrap_or("");
121 let filter_len = u32::try_from(filter.len()).expect("filter is too long");
122 let _ = unsafe {
123 libddwaf_sys::ddwaf_builder_get_config_paths(
124 self.raw,
125 res.as_raw_mut(),
126 filter.as_ptr().cast(),
127 filter_len,
128 )
129 };
130 res
131 }
132
133 #[must_use]
138 pub fn build(&mut self) -> Option<Handle> {
139 let raw = unsafe { libddwaf_sys::ddwaf_builder_build_instance(self.raw) };
140 if raw.is_null() {
141 return None;
142 }
143 Some(Handle { raw })
144 }
145}
146impl Drop for Builder {
147 fn drop(&mut self) {
148 unsafe { libddwaf_sys::ddwaf_builder_destroy(self.raw) }
149 }
150}
151
152unsafe impl Send for Builder {}
154unsafe impl Sync for Builder {}