oo_bindgen/model/structs/
common.rs

1use std::collections::HashSet;
2use std::fmt::{Debug, Formatter};
3use std::marker::PhantomData;
4use std::rc::Rc;
5use std::time::Duration;
6
7use crate::model::*;
8
9/// A numeric value
10#[non_exhaustive]
11#[derive(Debug, Copy, Clone, PartialEq)]
12pub enum NumberValue {
13    U8(u8),
14    S8(i8),
15    U16(u16),
16    S16(i16),
17    U32(u32),
18    S32(i32),
19    U64(u64),
20    S64(i64),
21    Float(f32),
22    Double(f64),
23}
24
25/// Default value for a field in struct initializer
26#[non_exhaustive]
27#[derive(Debug, Clone, PartialEq)]
28pub enum InitializerDefault {
29    Bool(bool),
30    Numeric(NumberValue),
31    Duration(Duration),
32    Enum(String),
33    String(String),
34    /// requires that the struct have a default initializer
35    DefaultStruct,
36}
37
38pub trait ToDefaultVariant {
39    fn default_variant(&self) -> InitializerDefault;
40}
41
42pub trait ToDefaultString {
43    fn default_string(&self) -> InitializerDefault;
44}
45
46impl ToDefaultVariant for &str {
47    fn default_variant(&self) -> InitializerDefault {
48        InitializerDefault::Enum(self.to_string())
49    }
50}
51
52impl ToDefaultString for &str {
53    fn default_string(&self) -> InitializerDefault {
54        InitializerDefault::String(self.to_string())
55    }
56}
57
58impl From<NumberValue> for InitializerDefault {
59    fn from(x: NumberValue) -> Self {
60        Self::Numeric(x)
61    }
62}
63
64impl From<bool> for InitializerDefault {
65    fn from(x: bool) -> Self {
66        InitializerDefault::Bool(x)
67    }
68}
69
70impl From<Duration> for InitializerDefault {
71    fn from(x: Duration) -> Self {
72        InitializerDefault::Duration(x)
73    }
74}
75
76// Value used to define a default in a struct initializer
77#[non_exhaustive]
78#[derive(Debug, Clone)]
79pub enum ValidatedDefaultValue {
80    Bool(bool),
81    Number(NumberValue),
82    Duration(DurationType, Duration),
83    Enum(Handle<Enum<Unvalidated>>, Name),
84    String(String),
85    /// requires that the struct have a default initializer
86    DefaultStruct(StructType<Unvalidated>, InitializerType, Name),
87}
88
89impl From<NumberValue> for ValidatedDefaultValue {
90    fn from(x: NumberValue) -> Self {
91        Self::Number(x)
92    }
93}
94
95impl std::fmt::Display for NumberValue {
96    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
97        match self {
98            Self::U8(x) => {
99                write!(f, "{x}")
100            }
101            Self::S8(x) => {
102                write!(f, "{x}")
103            }
104            Self::U16(x) => {
105                write!(f, "{x}")
106            }
107            Self::S16(x) => {
108                write!(f, "{x}")
109            }
110            Self::U32(x) => {
111                write!(f, "{x}")
112            }
113            Self::S32(x) => {
114                write!(f, "{x}")
115            }
116            Self::U64(x) => {
117                write!(f, "{x}")
118            }
119            Self::S64(x) => {
120                write!(f, "{x}")
121            }
122            Self::Float(x) => {
123                write!(f, "{x}")
124            }
125            Self::Double(x) => {
126                write!(f, "{x}")
127            }
128        }
129    }
130}
131
132impl std::fmt::Display for ValidatedDefaultValue {
133    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
134        match self {
135            Self::Bool(x) => {
136                write!(f, "{x}")
137            }
138            Self::Number(x) => write!(f, "{x}"),
139            Self::Duration(t, x) => match t {
140                DurationType::Milliseconds => write!(f, "{} milliseconds", x.as_millis()),
141                DurationType::Seconds => write!(f, "{} seconds", x.as_secs()),
142            },
143            Self::Enum(handle, x) => {
144                write!(f, "{}::{}", handle.name, x)
145            }
146            Self::String(x) => {
147                write!(f, "'{x}'")
148            }
149            Self::DefaultStruct(x, _, _) => {
150                write!(f, "default constructed value for {}", x.name())
151            }
152        }
153    }
154}
155
156/// struct type affects the type of code the backend will generate
157#[derive(Copy, Clone, Debug, PartialEq, Eq)]
158pub(crate) enum Visibility {
159    /// struct members are public
160    Public,
161    /// struct members are private (except C of course), and the struct is just an opaque "token"
162    Private,
163}
164
165/// C-style structure forward declaration
166#[derive(Debug)]
167pub struct StructDeclaration {
168    pub(crate) name: Name,
169    pub(crate) settings: Rc<LibrarySettings>,
170}
171
172impl StructDeclaration {
173    pub(crate) fn new(name: Name, settings: Rc<LibrarySettings>) -> Self {
174        Self { name, settings }
175    }
176}
177
178pub type StructDeclarationHandle = Handle<StructDeclaration>;
179
180/// Typed wrapper around an untyped struct declaration
181#[derive(Debug, Clone, Eq)]
182pub struct TypedStructDeclaration<T> {
183    pub(crate) inner: StructDeclarationHandle,
184    phantom: PhantomData<T>,
185}
186
187impl<T> AsRef<StructDeclarationHandle> for TypedStructDeclaration<T> {
188    fn as_ref(&self) -> &StructDeclarationHandle {
189        &self.inner
190    }
191}
192
193impl<T> PartialEq for TypedStructDeclaration<T> {
194    fn eq(&self, other: &Self) -> bool {
195        self.inner == other.inner
196    }
197}
198
199impl<T> TypedStructDeclaration<T> {
200    pub(crate) fn new(inner: StructDeclarationHandle) -> Self {
201        Self {
202            inner,
203            phantom: Default::default(),
204        }
205    }
206
207    pub fn name(&self) -> &Name {
208        &self.inner.name
209    }
210}
211
212pub type UniversalStructDeclaration = TypedStructDeclaration<UniversalStructField>;
213pub type FunctionArgStructDeclaration = TypedStructDeclaration<FunctionArgStructField>;
214pub type FunctionReturnStructDeclaration = TypedStructDeclaration<FunctionReturnStructField>;
215pub type CallbackArgStructDeclaration = TypedStructDeclaration<CallbackArgStructField>;
216
217pub trait InitializerValidator {
218    fn bad_initializer_value(
219        field_type: String,
220        value: &InitializerDefault,
221    ) -> BindResult<ValidatedDefaultValue> {
222        Err(BindingErrorVariant::StructInitializerBadValueForType {
223            field_type,
224            value: value.clone(),
225        }
226        .into())
227    }
228
229    /// Check that the value is valid for the type
230    fn validate_default_value(
231        &self,
232        value: &InitializerDefault,
233    ) -> BindResult<ValidatedDefaultValue>;
234}
235
236impl InitializerValidator for AbstractIteratorHandle {
237    fn validate_default_value(
238        &self,
239        value: &InitializerDefault,
240    ) -> BindResult<ValidatedDefaultValue> {
241        Self::bad_initializer_value("IteratorHandle".to_string(), value)
242    }
243}
244
245impl InitializerValidator for ClassDeclarationHandle {
246    fn validate_default_value(
247        &self,
248        value: &InitializerDefault,
249    ) -> BindResult<ValidatedDefaultValue> {
250        Self::bad_initializer_value("ClassHandle".to_string(), value)
251    }
252}
253
254impl InitializerValidator for InterfaceHandle {
255    fn validate_default_value(
256        &self,
257        value: &InitializerDefault,
258    ) -> BindResult<ValidatedDefaultValue> {
259        Self::bad_initializer_value("InterfaceHandle".to_string(), value)
260    }
261}
262
263impl InitializerValidator for CollectionHandle {
264    fn validate_default_value(
265        &self,
266        value: &InitializerDefault,
267    ) -> BindResult<ValidatedDefaultValue> {
268        Self::bad_initializer_value("CollectionHandle".to_string(), value)
269    }
270}
271
272impl InitializerValidator for StringType {
273    fn validate_default_value(
274        &self,
275        value: &InitializerDefault,
276    ) -> BindResult<ValidatedDefaultValue> {
277        match value {
278            InitializerDefault::String(x) => Ok(ValidatedDefaultValue::String(x.clone())),
279            _ => Self::bad_initializer_value("String".to_string(), value),
280        }
281    }
282}
283
284pub trait StructFieldType: Clone + Sized + InitializerValidator {
285    /// convert a structure to a StructType
286    fn create_struct_type(v: Handle<Struct<Self, Unvalidated>>) -> StructType<Unvalidated>;
287}
288
289#[derive(Debug)]
290pub struct StructField<F, D>
291where
292    F: StructFieldType,
293    D: DocReference,
294{
295    pub(crate) name: Name,
296    pub(crate) field_type: F,
297    pub(crate) doc: Doc<D>,
298}
299
300impl<F> StructField<F, Unvalidated>
301where
302    F: StructFieldType,
303{
304    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<StructField<F, Validated>> {
305        Ok(StructField {
306            name: self.name.clone(),
307            field_type: self.field_type.clone(),
308            doc: self.doc.validate(&self.name, lib)?,
309        })
310    }
311}
312
313/// C-style structure definition
314#[derive(Debug)]
315pub struct Struct<F, D>
316where
317    F: StructFieldType,
318    D: DocReference,
319{
320    pub(crate) visibility: Visibility,
321    pub(crate) declaration: TypedStructDeclaration<F>,
322    pub(crate) fields: Vec<StructField<F, D>>,
323    pub(crate) initializers: Vec<Handle<Initializer<D>>>,
324    pub(crate) doc: Doc<D>,
325}
326
327impl<F> Struct<F, Unvalidated>
328where
329    F: StructFieldType,
330{
331    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<Handle<Struct<F, Validated>>> {
332        let fields: BindResult<Vec<StructField<F, Validated>>> =
333            self.fields.iter().map(|x| x.validate(lib)).collect();
334        let initializers: BindResult<Vec<Initializer<Validated>>> =
335            self.initializers.iter().map(|x| x.validate(lib)).collect();
336        let initializers: Vec<Handle<Initializer<Validated>>> = initializers?
337            .iter()
338            .map(|x| Handle::new(x.clone()))
339            .collect();
340
341        Ok(Handle::new(Struct {
342            visibility: self.visibility,
343            declaration: self.declaration.clone(),
344            fields: fields?,
345            initializers,
346            doc: self.doc.validate(self.name(), lib)?,
347        }))
348    }
349}
350
351impl<F> InitializerValidator for Handle<Struct<F, Unvalidated>>
352where
353    F: StructFieldType,
354{
355    fn validate_default_value(
356        &self,
357        value: &InitializerDefault,
358    ) -> BindResult<ValidatedDefaultValue> {
359        match value {
360            InitializerDefault::DefaultStruct => match self.get_default_initializer() {
361                Some(c) => Ok(ValidatedDefaultValue::DefaultStruct(
362                    F::create_struct_type(self.clone()),
363                    c.initializer_type,
364                    c.name.clone(),
365                )),
366                None => Err(
367                    BindingErrorVariant::StructInitializerStructFieldWithoutDefaultInitializer {
368                        struct_name: self.name().to_string(),
369                    }
370                    .into(),
371                ),
372            },
373            _ => Err(BindingErrorVariant::StructInitializerBadValueForType {
374                field_type: "Struct".to_string(),
375                value: value.clone(),
376            }
377            .into()),
378        }
379    }
380}
381
382impl<F, D> Struct<F, D>
383where
384    F: StructFieldType,
385    D: DocReference,
386{
387    pub fn settings(&self) -> &LibrarySettings {
388        &self.declaration.inner.settings
389    }
390
391    pub fn find_field_name(&self, name: &str) -> Option<Name> {
392        self.fields
393            .iter()
394            .find(|x| x.name == name)
395            .map(|x| x.name.clone())
396    }
397
398    pub fn name(&self) -> &Name {
399        &self.declaration.inner.name
400    }
401
402    pub fn declaration(&self) -> StructDeclarationHandle {
403        self.declaration.inner.clone()
404    }
405
406    pub fn initializer_args(
407        &self,
408        initializer: Handle<Initializer<D>>,
409    ) -> impl Iterator<Item = &StructField<F, D>> {
410        self.fields
411            .iter()
412            .filter(move |field| !initializer.values.iter().any(|c| c.name == field.name))
413    }
414
415    pub fn fields(&self) -> impl Iterator<Item = &StructField<F, D>> {
416        self.fields.iter()
417    }
418
419    pub fn has_default_initializer(&self) -> bool {
420        self.get_default_initializer().is_some()
421    }
422
423    pub fn has_full_initializer(&self) -> bool {
424        self.get_full_initializer().is_some()
425    }
426
427    pub fn get_default_initializer(&self) -> Option<&Handle<Initializer<D>>> {
428        // Are any of the initializers of normal type and initialize ALL of the fields
429        self.initializers.iter().find(|c| {
430            c.initializer_type == InitializerType::Normal && c.values.len() == self.fields.len()
431        })
432    }
433
434    pub fn get_full_initializer(&self) -> Option<&Handle<Initializer<D>>> {
435        self.initializers.iter().find(|c| c.values.is_empty())
436    }
437}
438
439#[derive(Debug, Clone)]
440pub(crate) struct InitializedValue {
441    pub(crate) name: Name,
442    pub(crate) value: ValidatedDefaultValue,
443}
444
445#[non_exhaustive]
446#[derive(Debug, Copy, Clone, PartialEq, Eq)]
447pub enum InitializerType {
448    /// Normal initializers map to actual language constructors
449    /// A name is still required as some languages (e.g. C) don't support
450    /// associated constructors and require free-standing functions instead
451    Normal,
452    /// Static initializers are mapped to static methods in languages that support them (e.g. C++, Java, C#)
453    Static,
454}
455
456impl InitializerType {
457    pub(crate) fn is_normal(&self) -> bool {
458        *self == InitializerType::Normal
459    }
460}
461
462/// An initializer defines how to construct a struct
463#[derive(Debug, Clone)]
464pub struct Initializer<D>
465where
466    D: DocReference,
467{
468    pub(crate) name: Name,
469    pub(crate) initializer_type: InitializerType,
470    pub(crate) values: Rc<Vec<InitializedValue>>,
471    pub(crate) doc: Doc<D>,
472}
473
474impl Initializer<Unvalidated> {
475    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<Initializer<Validated>> {
476        Ok(Initializer {
477            name: self.name.clone(),
478            initializer_type: self.initializer_type,
479            values: self.values.clone(),
480            doc: self.doc.validate(&self.name, lib)?,
481        })
482    }
483}
484
485impl<D> Initializer<D>
486where
487    D: DocReference,
488{
489    fn argument_names(&self) -> HashSet<Name> {
490        self.values
491            .iter()
492            .map(|x| x.name.clone())
493            .collect::<HashSet<Name>>()
494    }
495
496    pub fn collides_with(&self, other: &Self) -> bool {
497        if self.argument_names() == other.argument_names() {
498            // this is only a problem if both are normal initializers
499            return self.initializer_type.is_normal() && other.initializer_type.is_normal();
500        }
501        false
502    }
503
504    pub fn full(initializer_type: InitializerType, doc: Doc<D>) -> Self {
505        Self {
506            name: Name::create("some_unused_name").unwrap(),
507            initializer_type,
508            values: Rc::new(Vec::new()),
509            doc,
510        }
511    }
512}
513
514#[non_exhaustive]
515#[derive(Debug, Clone, Hash, Eq, PartialEq)]
516pub enum StructType<D>
517where
518    D: DocReference,
519{
520    /// structs that may be used as native function parameters
521    FunctionArg(Handle<Struct<FunctionArgStructField, D>>),
522    /// structs than can be used as native function return values
523    FunctionReturn(Handle<Struct<FunctionReturnStructField, D>>),
524    /// structs that may be used as callback function arguments in interfaces
525    CallbackArg(Handle<Struct<CallbackArgStructField, D>>),
526    /// structs that can be used in any context and only contain basic types
527    Universal(Handle<Struct<UniversalStructField, D>>),
528}
529
530impl StructType<Unvalidated> {
531    pub(crate) fn validate(&self, lib: &LibraryFields) -> BindResult<StructType<Validated>> {
532        match self {
533            StructType::FunctionArg(x) => Ok(StructType::FunctionArg(x.validate(lib)?)),
534            StructType::FunctionReturn(x) => Ok(StructType::FunctionReturn(x.validate(lib)?)),
535            StructType::CallbackArg(x) => Ok(StructType::CallbackArg(x.validate(lib)?)),
536            StructType::Universal(x) => Ok(StructType::Universal(x.validate(lib)?)),
537        }
538    }
539}
540
541impl From<FunctionArgStructHandle> for StructType<Unvalidated> {
542    fn from(x: FunctionArgStructHandle) -> Self {
543        StructType::FunctionArg(x)
544    }
545}
546
547impl From<FunctionReturnStructHandle> for StructType<Unvalidated> {
548    fn from(x: FunctionReturnStructHandle) -> Self {
549        StructType::FunctionReturn(x)
550    }
551}
552
553impl From<CallbackArgStructHandle> for StructType<Unvalidated> {
554    fn from(x: CallbackArgStructHandle) -> Self {
555        StructType::CallbackArg(x)
556    }
557}
558
559impl From<UniversalStructHandle> for StructType<Unvalidated> {
560    fn from(x: UniversalStructHandle) -> Self {
561        StructType::Universal(x)
562    }
563}
564
565/// Structs refs can always be the Universal struct type, but may also be a
566/// more specific type depending on context
567#[non_exhaustive]
568#[derive(Debug, Clone)]
569pub enum UniversalDeclarationOr<T>
570where
571    T: StructFieldType,
572{
573    Specific(TypedStructDeclaration<T>),
574    Universal(UniversalStructDeclaration),
575}
576
577impl<T> UniversalDeclarationOr<T>
578where
579    T: StructFieldType,
580{
581    pub fn untyped(&self) -> &StructDeclarationHandle {
582        match self {
583            UniversalDeclarationOr::Specific(x) => &x.inner,
584            UniversalDeclarationOr::Universal(x) => &x.inner,
585        }
586    }
587}
588
589impl<T> PartialEq for UniversalDeclarationOr<T>
590where
591    T: StructFieldType,
592{
593    fn eq(&self, other: &Self) -> bool {
594        match self {
595            UniversalDeclarationOr::Specific(y) => match other {
596                UniversalDeclarationOr::Specific(x) => y == x,
597                UniversalDeclarationOr::Universal(_) => false,
598            },
599            UniversalDeclarationOr::Universal(x) => match other {
600                UniversalDeclarationOr::Specific(_) => false,
601                UniversalDeclarationOr::Universal(y) => x == y,
602            },
603        }
604    }
605}
606
607impl<T> Eq for UniversalDeclarationOr<T> where T: StructFieldType {}
608
609/// Structs can always be the Universal struct type, but may also be a
610/// more specific type depending on context
611#[non_exhaustive]
612#[derive(Debug, Clone, Eq)]
613pub enum UniversalOr<T>
614where
615    T: StructFieldType,
616{
617    Specific(Handle<Struct<T, Unvalidated>>),
618    Universal(UniversalStructHandle),
619}
620
621impl<T> PartialEq for UniversalOr<T>
622where
623    T: StructFieldType,
624{
625    fn eq(&self, other: &Self) -> bool {
626        match self {
627            UniversalOr::Specific(y) => match other {
628                UniversalOr::Specific(x) => y == x,
629                UniversalOr::Universal(_) => false,
630            },
631            UniversalOr::Universal(x) => match other {
632                UniversalOr::Specific(_) => false,
633                UniversalOr::Universal(y) => x == y,
634            },
635        }
636    }
637}
638
639impl<T> UniversalOr<T>
640where
641    T: StructFieldType,
642{
643    pub fn name(&self) -> &Name {
644        match self {
645            UniversalOr::Specific(x) => x.name(),
646            UniversalOr::Universal(x) => x.name(),
647        }
648    }
649
650    pub fn declaration(&self) -> StructDeclarationHandle {
651        match self {
652            UniversalOr::Specific(x) => x.declaration.inner.clone(),
653            UniversalOr::Universal(x) => x.declaration.inner.clone(),
654        }
655    }
656
657    pub fn typed_declaration(&self) -> UniversalDeclarationOr<T> {
658        match self {
659            UniversalOr::Specific(x) => UniversalDeclarationOr::Specific(x.declaration.clone()),
660            UniversalOr::Universal(x) => UniversalDeclarationOr::Universal(x.declaration.clone()),
661        }
662    }
663
664    pub fn to_struct_type(&self) -> StructType<Unvalidated> {
665        match self {
666            UniversalOr::Specific(x) => T::create_struct_type(x.clone()),
667            UniversalOr::Universal(x) => StructType::Universal(x.clone()),
668        }
669    }
670}
671
672impl<T> InitializerValidator for UniversalOr<T>
673where
674    T: StructFieldType,
675{
676    fn validate_default_value(
677        &self,
678        value: &InitializerDefault,
679    ) -> BindResult<ValidatedDefaultValue> {
680        match self {
681            UniversalOr::Specific(x) => x.validate_default_value(value),
682            UniversalOr::Universal(x) => x.validate_default_value(value),
683        }
684    }
685}
686
687impl<T> From<Handle<Struct<T, Unvalidated>>> for UniversalOr<T>
688where
689    T: StructFieldType,
690{
691    fn from(x: Handle<Struct<T, Unvalidated>>) -> Self {
692        UniversalOr::Specific(x)
693    }
694}
695
696impl<D> StructType<D>
697where
698    D: DocReference,
699{
700    pub fn initializers(&self) -> &[Handle<Initializer<D>>] {
701        match self {
702            StructType::FunctionArg(x) => &x.initializers,
703            StructType::FunctionReturn(x) => &x.initializers,
704            StructType::CallbackArg(x) => &x.initializers,
705            StructType::Universal(x) => &x.initializers,
706        }
707    }
708
709    pub fn name(&self) -> &Name {
710        match self {
711            StructType::FunctionArg(x) => x.name(),
712            StructType::CallbackArg(x) => x.name(),
713            StructType::FunctionReturn(x) => x.name(),
714            StructType::Universal(x) => x.name(),
715        }
716    }
717
718    pub fn doc(&self) -> &Doc<D> {
719        match self {
720            StructType::FunctionArg(x) => &x.doc,
721            StructType::FunctionReturn(x) => &x.doc,
722            StructType::CallbackArg(x) => &x.doc,
723            StructType::Universal(x) => &x.doc,
724        }
725    }
726
727    pub fn settings(&self) -> &LibrarySettings {
728        match self {
729            StructType::FunctionArg(x) => &x.declaration.inner.settings,
730            StructType::FunctionReturn(x) => &x.declaration.inner.settings,
731            StructType::CallbackArg(x) => &x.declaration.inner.settings,
732            StructType::Universal(x) => &x.declaration.inner.settings,
733        }
734    }
735
736    pub fn declaration(&self) -> StructDeclarationHandle {
737        match self {
738            StructType::FunctionArg(x) => x.declaration.inner.clone(),
739            StructType::CallbackArg(x) => x.declaration.inner.clone(),
740            StructType::FunctionReturn(x) => x.declaration.inner.clone(),
741            StructType::Universal(x) => x.declaration.inner.clone(),
742        }
743    }
744
745    pub fn find_field_name(&self, name: &str) -> Option<Name> {
746        match self {
747            StructType::FunctionArg(x) => x.find_field_name(name),
748            StructType::CallbackArg(x) => x.find_field_name(name),
749            StructType::FunctionReturn(x) => x.find_field_name(name),
750            StructType::Universal(x) => x.find_field_name(name),
751        }
752    }
753
754    pub fn get_default_initializer(&self) -> Option<&Handle<Initializer<D>>> {
755        match self {
756            StructType::FunctionArg(x) => x.get_default_initializer(),
757            StructType::FunctionReturn(x) => x.get_default_initializer(),
758            StructType::CallbackArg(x) => x.get_default_initializer(),
759            StructType::Universal(x) => x.get_default_initializer(),
760        }
761    }
762}