oo_bindgen/model/builder/
interface.rs1use std::collections::HashSet;
2
3use crate::model::*;
4
5pub struct InterfaceBuilder<'a> {
6 lib: &'a mut LibraryBuilder,
7 name: Name,
8 callbacks: Vec<CallbackFunction<Unvalidated>>,
9 callback_names: HashSet<String>,
10 doc: Doc<Unvalidated>,
11}
12
13impl<'a> InterfaceBuilder<'a> {
14 pub(crate) fn new(lib: &'a mut LibraryBuilder, name: Name, doc: Doc<Unvalidated>) -> Self {
15 Self {
16 lib,
17 name,
18 callbacks: Vec::new(),
19 callback_names: Default::default(),
20 doc,
21 }
22 }
23
24 pub fn begin_callback<T: IntoName, D: Into<Doc<Unvalidated>>>(
25 mut self,
26 name: T,
27 doc: D,
28 ) -> BindResult<CallbackFunctionBuilder<'a>> {
29 let name = name.into_name()?;
30 self.check_unique_callback_name(&name)?;
31 Ok(CallbackFunctionBuilder::new(self, name, doc.into()))
32 }
33
34 pub fn build_sync(self) -> BindResult<SynchronousInterface> {
40 let (handle, lib) = self.build(InterfaceCategory::Synchronous);
41 lib.add_statement(Statement::InterfaceDefinition(InterfaceType::Synchronous(
42 handle.clone(),
43 )))?;
44 Ok(SynchronousInterface { inner: handle })
45 }
46
47 pub fn build_async(self) -> BindResult<AsynchronousInterface> {
54 let (handle, lib) = self.build(InterfaceCategory::Asynchronous);
55 lib.add_statement(Statement::InterfaceDefinition(InterfaceType::Asynchronous(
56 handle.clone(),
57 )))?;
58 Ok(AsynchronousInterface { inner: handle })
59 }
60
61 pub(crate) fn build(
62 self,
63 mode: InterfaceCategory,
64 ) -> (InterfaceHandle, &'a mut LibraryBuilder) {
65 let handle = Handle::new(Interface {
66 name: self.name,
67 mode,
68 callbacks: self.callbacks,
69 doc: self.doc,
70 settings: self.lib.clone_settings(),
71 });
72
73 (handle, self.lib)
74 }
75
76 fn check_unique_callback_name(&mut self, name: &Name) -> BindResult<()> {
77 if name == &self.lib.settings().interface.destroy_func_name {
78 return Err(BindingErrorVariant::InterfaceMethodWithReservedName {
79 name: self.lib.settings().interface.destroy_func_name.clone(),
80 }
81 .into());
82 }
83
84 if name == &self.lib.settings().interface.context_variable_name.clone() {
85 return Err(BindingErrorVariant::InterfaceMethodWithReservedName {
86 name: self.lib.settings().interface.context_variable_name.clone(),
87 }
88 .into());
89 }
90
91 if self.callback_names.insert(name.to_string()) {
92 Ok(())
93 } else {
94 Err(BindingErrorVariant::InterfaceDuplicateCallbackName {
95 interface_name: self.name.clone(),
96 callback_name: name.clone(),
97 }
98 .into())
99 }
100 }
101}
102
103pub struct CallbackFunctionBuilder<'a> {
104 builder: InterfaceBuilder<'a>,
105 name: Name,
106 functional_transform: FunctionalTransform,
107 return_type: OptionalReturnType<CallbackReturnValue, Unvalidated>,
108 default_implementation: Option<DefaultCallbackReturnValue>,
109 arguments: Vec<Arg<CallbackArgument, Unvalidated>>,
110 doc: Doc<Unvalidated>,
111}
112
113impl<'a> CallbackFunctionBuilder<'a> {
114 pub(crate) fn new(builder: InterfaceBuilder<'a>, name: Name, doc: Doc<Unvalidated>) -> Self {
115 Self {
116 builder,
117 name,
118 functional_transform: FunctionalTransform::No,
119 return_type: OptionalReturnType::new(),
120 default_implementation: None,
121 arguments: Vec::new(),
122 doc,
123 }
124 }
125
126 #[must_use]
127 pub fn enable_functional_transform(mut self) -> Self {
128 self.functional_transform = FunctionalTransform::Yes;
129 self
130 }
131
132 pub fn param<S: IntoName, D: Into<DocString<Unvalidated>>, P: Into<CallbackArgument>>(
133 mut self,
134 name: S,
135 arg_type: P,
136 doc: D,
137 ) -> BindResult<Self> {
138 let arg_type = arg_type.into();
139 let name = name.into_name()?;
140
141 if name == self.builder.lib.settings().interface.context_variable_name {
142 return Err(
143 BindingErrorVariant::CallbackMethodArgumentWithReservedName {
144 name: self
145 .builder
146 .lib
147 .settings()
148 .interface
149 .context_variable_name
150 .clone(),
151 }
152 .into(),
153 );
154 }
155
156 self.arguments.push(Arg::new(arg_type, name, doc.into()));
157 Ok(self)
158 }
159
160 pub fn returns<T: Into<CallbackReturnValue>, D: Into<DocString<Unvalidated>>>(
161 mut self,
162 t: T,
163 d: D,
164 ) -> BindResult<Self> {
165 self.return_type.set(&self.name, t.into(), d.into())?;
166 Ok(self)
167 }
168
169 pub fn returns_with_default<
170 T: Into<DefaultCallbackReturnValue>,
171 D: Into<DocString<Unvalidated>>,
172 >(
173 self,
174 t: T,
175 d: D,
176 ) -> BindResult<Self> {
177 let default: DefaultCallbackReturnValue = t.into();
178
179 let mut ret = if let Some(return_type) = default.get_callback_return_value() {
180 self.returns(return_type, d)?
182 } else {
183 self
184 };
185
186 ret.default_implementation = Some(default);
187
188 Ok(ret)
189 }
190
191 pub fn returns_nothing_by_default(mut self) -> BindResult<Self> {
192 if self.return_type.is_some() {
194 return Err(BindingErrorVariant::ReturnTypeAlreadyDefined {
195 func_name: self.name,
196 }
197 .into());
198 }
199
200 self.default_implementation = Some(DefaultCallbackReturnValue::Void);
201
202 Ok(self)
203 }
204
205 pub fn end_callback(mut self) -> BindResult<InterfaceBuilder<'a>> {
206 let cb = CallbackFunction {
207 name: self.name,
208 functional_transform: self.functional_transform,
209 return_type: self.return_type,
210 default_implementation: self.default_implementation,
211 arguments: self.arguments,
212 doc: self.doc,
213 };
214
215 self.builder.callbacks.push(cb);
216 Ok(self.builder)
217 }
218}