oo_bindgen/model/
interface.rs

1use std::rc::Rc;
2
3use crate::model::*;
4
5/// Types allowed in callback function arguments
6#[non_exhaustive]
7#[derive(Debug, Clone, PartialEq)]
8pub enum CallbackArgument {
9    Basic(BasicType),
10    String(StringType),
11    Iterator(AbstractIteratorHandle),
12    Class(ClassDeclarationHandle),
13    Struct(UniversalOr<CallbackArgStructField>),
14}
15
16impl From<BasicType> for CallbackArgument {
17    fn from(x: BasicType) -> Self {
18        Self::Basic(x)
19    }
20}
21
22impl From<Primitive> for CallbackArgument {
23    fn from(x: Primitive) -> Self {
24        Self::Basic(x.into())
25    }
26}
27
28impl From<Handle<Enum<Unvalidated>>> for CallbackArgument {
29    fn from(x: Handle<Enum<Unvalidated>>) -> Self {
30        Self::Basic(BasicType::Enum(x))
31    }
32}
33
34impl From<DurationType> for CallbackArgument {
35    fn from(x: DurationType) -> Self {
36        CallbackArgument::Basic(BasicType::Duration(x))
37    }
38}
39
40impl From<AbstractIteratorHandle> for CallbackArgument {
41    fn from(x: AbstractIteratorHandle) -> Self {
42        Self::Iterator(x)
43    }
44}
45
46impl From<UniversalStructHandle> for CallbackArgument {
47    fn from(x: UniversalStructHandle) -> Self {
48        Self::Struct(UniversalOr::Universal(x))
49    }
50}
51
52impl From<CallbackArgStructHandle> for CallbackArgument {
53    fn from(x: CallbackArgStructHandle) -> Self {
54        Self::Struct(x.into())
55    }
56}
57
58impl From<StringType> for CallbackArgument {
59    fn from(x: StringType) -> Self {
60        Self::String(x)
61    }
62}
63
64impl From<ClassDeclarationHandle> for CallbackArgument {
65    fn from(x: ClassDeclarationHandle) -> Self {
66        Self::Class(x)
67    }
68}
69
70/// An enum handle and a default validated variant
71#[derive(Debug, Clone)]
72pub struct EnumValue {
73    pub(crate) handle: EnumHandle,
74    pub(crate) variant: EnumVariant<Unvalidated>,
75}
76
77impl EnumValue {
78    pub(crate) fn new(handle: EnumHandle, variant: &'static str) -> BindResult<Self> {
79        let variant = handle.validate_contains_variant_name(variant)?.clone();
80        Ok(Self { handle, variant })
81    }
82}
83
84/// Struct handle combined with the validated name of one of it's initializers.
85/// The initializer may not take parameters
86#[derive(Debug, Clone)]
87pub struct ZeroParameterStructInitializer {
88    pub(crate) handle: UniversalStructHandle,
89    pub(crate) initializer: Handle<Initializer<Unvalidated>>,
90}
91
92impl ZeroParameterStructInitializer {
93    fn try_create(handle: UniversalStructHandle, name: &'static str) -> BindResult<Self> {
94        let initializer = match handle.initializers.iter().find(|x| x.name == name) {
95            None => {
96                return Err(BindingErrorVariant::InitializerDoesNotExist {
97                    name,
98                    struct_name: handle.declaration.name().clone(),
99                }
100                .into())
101            }
102            Some(x) => x.clone(),
103        };
104
105        // all values must be initialized
106        if initializer.values.len() != handle.fields.len() {
107            return Err(BindingErrorVariant::InitializerNotParameterless {
108                name,
109                struct_name: handle.declaration.name().clone(),
110            }
111            .into());
112        }
113
114        Ok(Self {
115            handle,
116            initializer,
117        })
118    }
119}
120
121impl UniversalStructHandle {
122    pub fn zero_parameter_initializer(
123        &self,
124        name: &'static str,
125    ) -> BindResult<ZeroParameterStructInitializer> {
126        ZeroParameterStructInitializer::try_create(self.clone(), name)
127    }
128}
129
130/// Like a BasicType but with values
131#[non_exhaustive]
132#[derive(Debug, Clone)]
133pub enum BasicValue {
134    Primitive(PrimitiveValue),
135    Duration(DurationValue),
136    Enum(EnumValue),
137}
138
139impl BasicValue {
140    pub(crate) fn get_basic_type(&self) -> BasicType {
141        match self {
142            BasicValue::Primitive(x) => {
143                let pv: PrimitiveValue = *x;
144                let x: Primitive = pv.into();
145                BasicType::Primitive(x)
146            }
147            BasicValue::Duration(x) => {
148                let dv: DurationValue = *x;
149                let dt: DurationType = dv.into();
150                BasicType::Duration(dt)
151            }
152            BasicValue::Enum(x) => BasicType::Enum(x.handle.clone()),
153        }
154    }
155}
156
157/// types that can be returned from callback functions
158#[non_exhaustive]
159#[derive(Debug, Clone, PartialEq, Eq)]
160pub enum CallbackReturnValue {
161    Basic(BasicType),
162    Struct(UniversalStructHandle),
163}
164
165/// Like CallbackReturnValue, but with a value
166#[non_exhaustive]
167#[derive(Debug, Clone)]
168pub enum DefaultCallbackReturnValue {
169    Void,
170    Basic(BasicValue),
171    InitializedStruct(ZeroParameterStructInitializer),
172}
173
174impl DefaultCallbackReturnValue {
175    pub(crate) fn get_callback_return_value(&self) -> Option<CallbackReturnValue> {
176        match self {
177            DefaultCallbackReturnValue::Void => None,
178            DefaultCallbackReturnValue::Basic(x) => {
179                Some(CallbackReturnValue::Basic(x.get_basic_type()))
180            }
181            DefaultCallbackReturnValue::InitializedStruct(x) => {
182                Some(CallbackReturnValue::Struct(x.handle.clone()))
183            }
184        }
185    }
186}
187
188impl From<ZeroParameterStructInitializer> for DefaultCallbackReturnValue {
189    fn from(x: ZeroParameterStructInitializer) -> Self {
190        DefaultCallbackReturnValue::InitializedStruct(x)
191    }
192}
193
194impl From<PrimitiveValue> for DefaultCallbackReturnValue {
195    fn from(x: PrimitiveValue) -> Self {
196        DefaultCallbackReturnValue::Basic(BasicValue::Primitive(x))
197    }
198}
199
200impl From<DurationValue> for DefaultCallbackReturnValue {
201    fn from(x: DurationValue) -> Self {
202        DefaultCallbackReturnValue::Basic(BasicValue::Duration(x))
203    }
204}
205
206impl From<EnumValue> for DefaultCallbackReturnValue {
207    fn from(x: EnumValue) -> Self {
208        DefaultCallbackReturnValue::Basic(BasicValue::Enum(x))
209    }
210}
211
212impl From<Primitive> for CallbackReturnValue {
213    fn from(x: Primitive) -> Self {
214        Self::Basic(x.into())
215    }
216}
217
218impl From<BasicType> for CallbackReturnValue {
219    fn from(x: BasicType) -> Self {
220        CallbackReturnValue::Basic(x)
221    }
222}
223
224impl From<UniversalStructHandle> for CallbackReturnValue {
225    fn from(x: UniversalStructHandle) -> Self {
226        CallbackReturnValue::Struct(x)
227    }
228}
229
230impl From<DurationType> for CallbackReturnValue {
231    fn from(x: DurationType) -> Self {
232        BasicType::Duration(x).into()
233    }
234}
235
236impl From<Handle<Enum<Unvalidated>>> for CallbackReturnValue {
237    fn from(x: Handle<Enum<Unvalidated>>) -> Self {
238        Self::Basic(BasicType::Enum(x))
239    }
240}
241
242pub type CallbackReturnType<T> = ReturnType<CallbackReturnValue, T>;
243
244/// A flag to the backend that tells it whether or not
245/// to optimize callbacks into Functors in the public API
246/// This flag is only inspected for functional interfaces
247#[non_exhaustive]
248#[derive(Debug, Copy, Clone, PartialEq, Eq)]
249pub enum FunctionalTransform {
250    /// If the interface is functional, it should be optimized into
251    /// functors if the language supports them
252    Yes,
253    /// If the interface is functional, it will NOT be transformed
254    No,
255}
256
257impl FunctionalTransform {
258    pub fn enabled(&self) -> bool {
259        match self {
260            FunctionalTransform::Yes => true,
261            FunctionalTransform::No => false,
262        }
263    }
264}
265
266#[derive(Debug)]
267pub(crate) struct CallbackFunction<D>
268where
269    D: DocReference,
270{
271    pub(crate) name: Name,
272    pub(crate) functional_transform: FunctionalTransform,
273    pub(crate) return_type: OptionalReturnType<CallbackReturnValue, D>,
274    pub(crate) default_implementation: Option<DefaultCallbackReturnValue>,
275    pub(crate) arguments: Vec<Arg<CallbackArgument, D>>,
276    pub(crate) doc: Doc<D>,
277}
278
279impl CallbackFunction<Unvalidated> {
280    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<CallbackFunction<Validated>> {
281        let arguments: BindResult<Vec<Arg<CallbackArgument, Validated>>> =
282            self.arguments.iter().map(|x| x.validate(lib)).collect();
283
284        let argument_names: Vec<Name> = self.arguments.iter().map(|x| x.name.clone()).collect();
285
286        Ok(CallbackFunction {
287            name: self.name.clone(),
288            functional_transform: self.functional_transform,
289            return_type: self.return_type.validate(&self.name, lib)?,
290            default_implementation: self.default_implementation.clone(),
291            arguments: arguments?,
292            doc: self
293                .doc
294                .validate_with_args(&self.name, lib, Some(&argument_names))?,
295        })
296    }
297}
298
299#[derive(Debug, Copy, Clone, PartialEq, Eq)]
300pub(crate) enum InterfaceCategory {
301    /// The interface will only be used in a synchronous context and the Rust
302    /// backend will not generate Sync / Send implementations so it cannot be sent
303    /// to other threads.
304    Synchronous,
305    /// The interface is used in asynchronous contexts where it will be invoked after
306    /// a function call using it. The Rust backend will generate unsafe Sync / Send
307    /// implementations allowing it to be based to other threads
308    Asynchronous,
309    /// An asynchronous interface which has particular properties
310    Future,
311}
312
313#[derive(Debug, Clone)]
314pub(crate) enum InterfaceType<D>
315where
316    D: DocReference,
317{
318    Synchronous(Handle<Interface<D>>),
319    Asynchronous(Handle<Interface<D>>),
320    Future(FutureInterface<D>),
321}
322
323impl InterfaceType<Unvalidated> {
324    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<InterfaceType<Validated>> {
325        match self {
326            InterfaceType::Synchronous(x) => Ok(InterfaceType::Synchronous(x.validate(lib)?)),
327            InterfaceType::Asynchronous(x) => Ok(InterfaceType::Asynchronous(x.validate(lib)?)),
328            InterfaceType::Future(x) => Ok(InterfaceType::Future(x.validate(lib)?)),
329        }
330    }
331}
332
333impl<D> InterfaceType<D>
334where
335    D: DocReference,
336{
337    pub(crate) fn name(&self) -> &Name {
338        match self {
339            InterfaceType::Synchronous(x) => &x.name,
340            InterfaceType::Asynchronous(x) => &x.name,
341            InterfaceType::Future(x) => &x.interface.name,
342        }
343    }
344
345    pub(crate) fn mode(&self) -> InterfaceCategory {
346        match self {
347            InterfaceType::Synchronous(_) => InterfaceCategory::Synchronous,
348            InterfaceType::Asynchronous(_) => InterfaceCategory::Asynchronous,
349            InterfaceType::Future(_) => InterfaceCategory::Future,
350        }
351    }
352
353    pub(crate) fn doc(&self) -> &Doc<D> {
354        match self {
355            InterfaceType::Synchronous(x) => &x.doc,
356            InterfaceType::Asynchronous(x) => &x.doc,
357            InterfaceType::Future(x) => &x.interface.doc,
358        }
359    }
360
361    pub(crate) fn untyped(&self) -> &Handle<Interface<D>> {
362        match self {
363            InterfaceType::Synchronous(x) => x,
364            InterfaceType::Asynchronous(x) => x,
365            InterfaceType::Future(x) => &x.interface,
366        }
367    }
368}
369
370#[derive(Debug)]
371pub struct Interface<D>
372where
373    D: DocReference,
374{
375    pub(crate) name: Name,
376    pub(crate) mode: InterfaceCategory,
377    pub(crate) callbacks: Vec<CallbackFunction<D>>,
378    pub(crate) doc: Doc<D>,
379    pub(crate) settings: Rc<LibrarySettings>,
380}
381
382impl Interface<Unvalidated> {
383    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<Handle<Interface<Validated>>> {
384        let callbacks: BindResult<Vec<CallbackFunction<Validated>>> =
385            self.callbacks.iter().map(|x| x.validate(lib)).collect();
386
387        Ok(Handle::new(Interface {
388            name: self.name.clone(),
389            mode: self.mode,
390            callbacks: callbacks?,
391            doc: self.doc.validate(&self.name, lib)?,
392            settings: self.settings.clone(),
393        }))
394    }
395}
396
397impl<D> Interface<D>
398where
399    D: DocReference,
400{
401    /// Return a reference to a CallbackFunction if and only if the interface has a single callback.
402    ///
403    /// This type of interface can be converted to a Functor-type in many backend languages
404    pub(crate) fn get_functional_callback(&self) -> Option<&CallbackFunction<D>> {
405        match self.callbacks.len() {
406            1 => self.callbacks.first(),
407            _ => None,
408        }
409    }
410
411    pub(crate) fn is_functional(&self) -> bool {
412        self.get_functional_callback().is_some()
413    }
414
415    pub(crate) fn find_callback<S: AsRef<str>>(&self, name: S) -> Option<&CallbackFunction<D>> {
416        self.callbacks
417            .iter()
418            .find(|callback| callback.name.as_ref() == name.as_ref())
419    }
420}
421
422pub type InterfaceHandle = Handle<Interface<Unvalidated>>;
423
424/// Declares that the contained interface is asynchronous
425///
426/// Acts as a "New Type" around an interface handle to restrict where it can be used in the API model
427#[derive(Debug, Clone)]
428pub struct AsynchronousInterface {
429    pub(crate) inner: InterfaceHandle,
430}
431
432/// Declares that the contained interface is synchronous only
433///
434/// Acts as a "New Type" around an interface handle to restrict where it can be used in the API model
435#[derive(Debug, Clone)]
436pub struct SynchronousInterface {
437    pub(crate) inner: InterfaceHandle,
438}
439
440#[derive(Debug, Clone)]
441pub struct FutureInterface<D>
442where
443    D: DocReference,
444{
445    pub(crate) value_type: CallbackArgument,
446    pub(crate) value_type_doc: DocString<D>,
447    pub(crate) error_type: ErrorType<D>,
448    pub(crate) interface: Handle<Interface<D>>,
449}
450
451impl FutureInterface<Unvalidated> {
452    pub(crate) fn new(
453        value_type: CallbackArgument,
454        error_type: ErrorType<Unvalidated>,
455        interface: Handle<Interface<Unvalidated>>,
456        value_type_doc: DocString<Unvalidated>,
457    ) -> Self {
458        Self {
459            value_type,
460            error_type,
461            value_type_doc,
462            interface,
463        }
464    }
465
466    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<FutureInterface<Validated>> {
467        Ok(FutureInterface {
468            value_type: self.value_type.clone(),
469            error_type: self.error_type.validate(lib)?,
470            value_type_doc: self.value_type_doc.validate(&self.interface.name, lib)?,
471            interface: self.interface.validate(lib)?,
472        })
473    }
474}
475
476pub type FutureInterfaceHandle = FutureInterface<Unvalidated>;