ferroui-base 0.3.0

The base library of FerroUI: the property system, layout, input, styling, media, text, animation, data binding and the compositor
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
//! Runtime type information and the class model of the object hierarchy.
//!
//! The framework is a deep single-inheritance class hierarchy with virtual
//! members. It is modelled as follows:
//!
//! * A class is a `#[repr(C)]` struct whose first field, `base`, is its base
//!   class. It derefs to the base, so inherited members are reached through
//!   auto-deref with static dispatch and no runtime cost.
//! * Objects live on the heap behind [`Ref<T>`], a reference-counted handle
//!   that can be upcast to any base class for free and downcast with a runtime
//!   check, like an object reference in a managed language.
//! * Virtual members are declared once with [`ferro_class!`]. For each class
//!   that introduces virtuals this generates a `<Class>Impl` trait whose
//!   associated functions are the overridable members. A subclass overrides a
//!   member by implementing the function; members it does not implement fall
//!   through to the nearest base class that does, and an override can call
//!   its base implementation with `parent_<member>`.
//! * Dispatch goes through one per-class table of function pointers. An
//!   object holds a single pointer to the table of its most-derived class.
//! * The slot of a member a class does not override holds the implementation
//!   the member falls through to, where the class states what it overrides
//!   ([`ferro_impl_classes!`], [`ferro_overrides!`]); otherwise it holds a
//!   function of the class that forwards to the table of its base class.
//!
//! All `unsafe` needed for this lives in this module and in the macros it
//! exports, and rests on two invariants that the macros establish and check
//! at compile time: a class struct starts with its base class at offset zero,
//! and a class's virtual table starts with its base class's virtual table.

use crate::metadata::{MarkupType, TypeOf};
use crate::{FerroObject, FerroProperty};
use std::any::{Any, TypeId};
use std::collections::HashMap;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::ops::Deref;
use std::rc::{Rc, Weak};
use std::sync::{OnceLock, RwLock};

/// Describes a class (or a non-instantiable type that owns attached
/// properties): its name, where it is declared, its base class, how to
/// initialise it and how to create an instance of it.
///
/// A `TypeInfo` is plain constant data, built by [`ferro_class!`] and
/// [`ferro_static_type!`].
pub struct TypeInfo {
    name: &'static str,
    base: Option<&'static TypeInfo>,
    module_path: &'static str,
    class_init: Option<fn()>,
    constructor: Option<fn() -> Ref<FerroObject>>,
    handles: Option<fn() -> [TypeId; 2]>,
    handle_registration: Option<fn()>,
    interfaces: &'static [TypeOf],
    markup: Option<&'static MarkupType>,
}

impl TypeInfo {
    pub const fn new(name: &'static str, base: Option<&'static TypeInfo>) -> Self {
        Self {
            name,
            base,
            module_path: "",
            class_init: None,
            constructor: None,
            handles: None,
            handle_registration: None,
            interfaces: &[],
            markup: None,
        }
    }

    /// States the Rust module that declares the type (`module_path!()` at
    /// the declaration). The markup-facing [`namespace`](Self::namespace) is
    /// derived from it.
    pub const fn with_module_path(mut self, module_path: &'static str) -> Self {
        self.module_path = module_path;
        self
    }

    /// Attaches the static initialisation of the type: a function that,
    /// once per thread and after doing the same for the base type, registers
    /// what the type declares (handle casts, property definitions) and runs
    /// its static constructor.
    ///
    /// It is what lets code that only has the runtime type (a lookup of a
    /// property by owner type and name) initialise a type that has no
    /// instance yet.
    pub const fn with_class_init(mut self, class_init: fn()) -> Self {
        self.class_init = Some(class_init);
        self
    }

    /// Attaches the default constructor of the class: the function that
    /// creates an instance as its parameterless `new()` does.
    pub const fn with_constructor(mut self, constructor: Option<fn() -> Ref<FerroObject>>) -> Self {
        self.constructor = constructor;
        self
    }

    /// States the Rust types of the handle of the class and of its nullable
    /// form (`Ref<T>`, `Option<Ref<T>>`), which makes the class findable by
    /// the type of a value ([`find_by_handle`](Self::find_by_handle)).
    pub const fn with_handles(mut self, handles: fn() -> [TypeId; 2]) -> Self {
        self.handles = Some(handles);
        self
    }

    /// States the registration of the handle of the class with the untyped
    /// value conversions
    /// ([`ValueTypes::register_object`](crate::data::core::ValueTypes::register_object)
    /// of the class): what makes `Ref<T>` an object handle and
    /// `Option<Ref<T>>` its nullable form. The initialisation of the class
    /// makes it on the thread that initialises the class; a class of a table
    /// of types ([`register_all`](Self::register_all)) has it on every thread,
    /// initialised or not, because a property of another class may hold the
    /// null of its handle before anything creates an instance of it.
    pub const fn with_handle_registration(mut self, handle_registration: fn()) -> Self {
        self.handle_registration = Some(handle_registration);
        self
    }

    /// States the interface handles the class declares
    /// ([`ferro_class_info!`], `interfaces`).
    pub const fn with_interfaces(mut self, interfaces: &'static [TypeOf]) -> Self {
        self.interfaces = interfaces;
        self
    }

    /// Attaches the markup metadata of the class ([`ferro_class_info!`],
    /// `markup`).
    pub const fn with_markup(mut self, markup: Option<&'static MarkupType>) -> Self {
        self.markup = markup;
        self
    }

    /// The class name, without namespace.
    #[inline]
    pub fn name(&self) -> &'static str {
        self.name
    }

    /// The direct base class, if any.
    #[inline]
    pub fn base_type(&self) -> Option<&'static TypeInfo> {
        self.base
    }

    /// The Rust module that declares the type, as `module_path!()` spells
    /// it (`ferroui_base::media::solid_color_brush`). Empty for a type whose
    /// runtime type was written by hand.
    #[inline]
    pub fn module_path(&self) -> &'static str {
        self.module_path
    }

    /// The dotted, markup-facing namespace of the type (`FerroUI.Media`).
    ///
    /// Namespaces are declared once per module, not per class: a crate maps
    /// its module paths to namespaces with [`TypeInfo::register_namespaces`]
    /// (from its `register_types()` function), and the namespace of a type
    /// is the one registered for the longest prefix of its
    /// [`module_path`](Self::module_path). Empty when no prefix is
    /// registered.
    pub fn namespace(&self) -> &'static str {
        let registry = read_registry();
        registry.namespace_of(self.module_path)
    }

    /// The dotted namespace registered for a Rust module path; see
    /// [`namespace`](Self::namespace).
    pub fn namespace_of_module(module_path: &str) -> &'static str {
        read_registry().namespace_of(module_path)
    }

    /// The namespace-qualified name of the type (`FerroUI.Media.Brush`).
    pub fn full_name(&self) -> String {
        match self.namespace() {
            "" => self.name.to_string(),
            namespace => format!("{namespace}.{}", self.name),
        }
    }

    /// Whether the type has a static initialisation of its own
    /// ([`with_class_init`](Self::with_class_init)).
    #[cfg(feature = "compiler-metadata")]
    pub(crate) fn has_class_init(&self) -> bool {
        self.class_init.is_some()
    }

    /// Ensures the static initialisation of the type and of its base types
    /// has run on the current thread: handle casts and property definitions
    /// are registered (properties in declaration order) and the static
    /// constructors have run, base types first. Does nothing after the first
    /// call on a thread.
    ///
    /// Called when the first instance of a class is created, when a property
    /// accessor of the type is first called and by the property registry when
    /// it is asked about the type; call it directly where the static
    /// constructor of a type must have run before none of these happened.
    #[inline]
    pub fn ensure_class_init(&self) {
        let mut current = Some(self);
        while let Some(type_) = current {
            if let Some(class_init) = type_.class_init {
                // An initialiser initialises its base types itself.
                class_init();
                return;
            }
            current = type_.base;
        }
    }

    /// The default constructor of the class, if it declares one (see
    /// [`ferro_class_info!`]): creates an instance as the parameterless
    /// `new()` of the class does.
    #[inline]
    pub fn default_constructor(&self) -> Option<fn() -> Ref<FerroObject>> {
        self.constructor
    }

    /// Creates an instance with the default constructor of the class.
    /// `None` if the class has none (abstract classes, classes that need
    /// constructor arguments, non-instantiable types).
    pub fn create_instance(&self) -> Option<Ref<FerroObject>> {
        self.constructor.map(|constructor| constructor())
    }

    /// The Rust type of the handle of the class (`Ref<T>`). `None` for types
    /// that are not classes.
    pub fn handle(&self) -> Option<TypeId> {
        self.handles.map(|handles| handles()[0])
    }

    /// The Rust type of the nullable handle of the class (`Option<Ref<T>>`).
    pub fn nullable_handle(&self) -> Option<TypeId> {
        self.handles.map(|handles| handles()[1])
    }

    /// The interface handles the class itself declares with
    /// [`ferro_class_info!`] (not the ones of its base classes).
    #[inline]
    pub fn interfaces(&self) -> &'static [TypeOf] {
        self.interfaces
    }

    /// The markup metadata the class itself declares with
    /// [`ferro_class_info!`]: its content property, plain properties,
    /// methods, events and attributes. `None` for a class that declares
    /// none; the metadata of its base classes still applies to it.
    #[inline]
    pub fn markup(&self) -> Option<&'static MarkupType> {
        self.markup
    }

    /// The name of the content property of the class: the one it declares,
    /// or else the one of the nearest base class that declares one.
    pub fn content_property(&self) -> Option<&'static str> {
        let mut current = Some(self);
        while let Some(type_) = current {
            if let Some(content) = type_.markup.and_then(|m| m.content_property) {
                return Some(content);
            }
            current = type_.base;
        }
        None
    }

    /// The properties registered on the type and its base types (styled,
    /// direct and the attached properties the type owns), each type's in
    /// declaration order, most derived type first. Initialises the type if
    /// needed, so no instance has to exist.
    pub fn properties(&'static self) -> Rc<Vec<&'static FerroProperty>> {
        crate::FerroPropertyRegistry::instance().get_registered(self)
    }

    /// Finds a property registered on the type or its base types by name.
    /// Initialises the type if needed.
    pub fn find_property(&'static self, name: &str) -> Option<&'static FerroProperty> {
        crate::FerroPropertyRegistry::instance().find_registered(self, name)
    }

    /// Adds a type to the process-wide table of known types, making it
    /// discoverable with [`find`](Self::find) and
    /// [`find_by_name`](Self::find_by_name). Registering a type again does
    /// nothing.
    ///
    /// Types register themselves when they are initialised on a thread; a
    /// crate's `register_types()` function registers all of its types up
    /// front so that types that were never used are known too.
    pub fn register(type_: &'static TypeInfo) {
        if read_registry().contains(type_) {
            return;
        }
        write_registry().insert(type_);
        // As for the types of a table: see `register_all`.
        if let Some(handle_registration) = type_.handle_registration {
            crate::data::core::ValueTypes::register_global(handle_registration);
        }
    }

    /// Registers several types; see [`register`](Self::register).
    ///
    /// The handle of each class is registered with the untyped value
    /// conversions of every thread as well
    /// ([`with_handle_registration`](Self::with_handle_registration)), when
    /// the thread next converts an untyped value: the nullable form of the
    /// handle of a class of a table is known whether or not the class has
    /// been initialised. A property typed with the handle of another class
    /// holds its null from the start (`Control.ContextMenu`), and what reads
    /// that value untyped (a binding, markup) must see null. The run-time
    /// XAML loader initialises a class when it reads it, which hid the
    /// difference; compiled markup names a class without initialising it.
    pub fn register_all(types: &[&'static TypeInfo]) {
        {
            let mut registry = write_registry();
            for type_ in types {
                registry.insert(type_);
            }
        }
        for type_ in types {
            if let Some(handle_registration) = type_.handle_registration {
                crate::data::core::ValueTypes::register_global(handle_registration);
            }
        }
    }

    /// Declares the namespaces of a crate's modules: pairs of a Rust module
    /// path (`"ferroui_base::media"`) and the dotted namespace of the types
    /// declared in that module and its submodules (`"FerroUI.Media"`). A
    /// longer module path overrides a shorter one, down to a single file.
    pub fn register_namespaces(namespaces: &[(&'static str, &'static str)]) {
        let mut registry = write_registry();
        for &(module_path, namespace) in namespaces {
            match registry.namespaces.iter_mut().find(|(m, _)| *m == module_path) {
                Some(entry) => entry.1 = namespace,
                None => registry.namespaces.push((module_path, namespace)),
            }
        }
    }

    #[cfg(feature = "compiler-metadata")]
    /// Declares the public Rust paths of classes: pairs of a class and the
    /// path another crate names it by (`"ferroui_controls::Border"`). The
    /// declaring module ([`module_path`](Self::module_path)) is often
    /// private, so the path cannot be derived from it; a crate records the
    /// table of its generated `rust_paths.rs` ([`ferro_rust_paths!`](crate::ferro_rust_paths))
    /// in its `register_types()`. The emitter of Rust source reads them;
    /// nothing else does.
    pub fn register_rust_paths(paths: &[(&'static TypeInfo, &'static str)]) {
        let mut registry = write_registry();
        for &(type_, path) in paths {
            registry.rust_paths.insert(type_ as *const TypeInfo as usize, (type_, path));
        }
    }

    #[cfg(feature = "compiler-metadata")]
    /// The public Rust path of the class
    /// ([`register_rust_paths`](Self::register_rust_paths)), if its crate
    /// recorded one.
    pub fn rust_path(&'static self) -> Option<&'static str> {
        read_registry().rust_paths.get(&(self as *const TypeInfo as usize)).map(|entry| entry.1)
    }

    #[cfg(feature = "compiler-metadata")]
    /// Every class with a registered public Rust path, with the path, in no
    /// particular order.
    pub fn all_rust_paths() -> Vec<(&'static TypeInfo, &'static str)> {
        read_registry().rust_paths.values().copied().collect()
    }

    /// Finds a known type by namespace and name.
    pub fn find(namespace: &str, name: &str) -> Option<&'static TypeInfo> {
        let registry = read_registry();
        let candidates = registry.by_name.get(name)?;
        candidates.iter().copied().find(|t| registry.namespace_of(t.module_path) == namespace)
    }

    /// Finds the known class whose handle (`Ref<T>`) or nullable handle
    /// (`Option<Ref<T>>`) is the Rust type `handle`. The flag tells whether
    /// it is the nullable handle.
    pub fn find_by_handle(handle: TypeId) -> Option<(&'static TypeInfo, bool)> {
        read_registry().by_handle.get(&handle).copied()
    }

    /// Finds a known type by name alone. `None` if no type or more than one
    /// type (in different namespaces) has the name.
    pub fn find_by_name(name: &str) -> Option<&'static TypeInfo> {
        let registry = read_registry();
        match registry.by_name.get(name)?.as_slice() {
            [type_] => Some(type_),
            _ => None,
        }
    }

    /// Every known type, in registration order.
    pub fn registered_types() -> Vec<&'static TypeInfo> {
        read_registry().types.clone()
    }

    /// Returns true if `other` is this type or derives from it.
    pub fn is_assignable_from(&self, other: &TypeInfo) -> bool {
        let mut current = Some(other);
        while let Some(t) = current {
            if std::ptr::eq(self, t) {
                return true;
            }
            current = t.base;
        }
        false
    }

    /// Returns true if this type is `other` or derives from it.
    #[inline]
    pub fn is_subclass_of(&self, other: &TypeInfo) -> bool {
        other.is_assignable_from(self)
    }
}

impl PartialEq for TypeInfo {
    #[inline]
    fn eq(&self, other: &Self) -> bool {
        std::ptr::eq(self, other)
    }
}

impl Eq for TypeInfo {}

impl Hash for TypeInfo {
    fn hash<H: Hasher>(&self, state: &mut H) {
        (self as *const TypeInfo as usize).hash(state)
    }
}

impl fmt::Debug for TypeInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name)
    }
}

impl fmt::Display for TypeInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(self.name)
    }
}

/// The process-wide table of known types. Runtime types are immutable
/// statics, so unlike the property registry the table is not per thread.
#[derive(Default)]
struct TypeRegistry {
    types: Vec<&'static TypeInfo>,
    by_name: HashMap<&'static str, Vec<&'static TypeInfo>>,
    by_handle: HashMap<TypeId, (&'static TypeInfo, bool)>,
    namespaces: Vec<(&'static str, &'static str)>,
    /// The public Rust paths of classes, by the address of their type.
    #[cfg(feature = "compiler-metadata")]
    rust_paths: HashMap<usize, (&'static TypeInfo, &'static str)>,
}

impl TypeRegistry {
    fn contains(&self, type_: &'static TypeInfo) -> bool {
        self.by_name.get(type_.name).is_some_and(|types| types.iter().any(|t| std::ptr::eq(*t, type_)))
    }

    fn insert(&mut self, type_: &'static TypeInfo) {
        if !self.contains(type_) {
            self.types.push(type_);
            self.by_name.entry(type_.name).or_default().push(type_);
            if let Some(handles) = type_.handles {
                let [handle, nullable] = handles();
                self.by_handle.insert(handle, (type_, false));
                self.by_handle.insert(nullable, (type_, true));
            }
        }
    }

    fn namespace_of(&self, module_path: &str) -> &'static str {
        let mut best: Option<(&'static str, &'static str)> = None;
        for &(prefix, namespace) in &self.namespaces {
            let matches = match module_path.strip_prefix(prefix) {
                Some(rest) => rest.is_empty() || rest.starts_with("::"),
                None => false,
            };
            if matches && best.is_none_or(|(b, _)| prefix.len() > b.len()) {
                best = Some((prefix, namespace));
            }
        }
        best.map_or("", |(_, namespace)| namespace)
    }
}

fn type_registry() -> &'static RwLock<TypeRegistry> {
    static REGISTRY: OnceLock<RwLock<TypeRegistry>> = OnceLock::new();
    REGISTRY.get_or_init(Default::default)
}

fn read_registry() -> std::sync::RwLockReadGuard<'static, TypeRegistry> {
    type_registry().read().unwrap_or_else(|e| e.into_inner())
}

fn write_registry() -> std::sync::RwLockWriteGuard<'static, TypeRegistry> {
    type_registry().write().unwrap_or_else(|e| e.into_inner())
}

/// A Rust type with an associated runtime [`TypeInfo`].
///
/// Implemented by all classes ([`ferro_class!`]) and by non-instantiable
/// types that own attached properties ([`ferro_static_type!`]).
pub trait StaticType: 'static {
    /// The runtime type.
    const TYPE: &'static TypeInfo;
}

/// What a type declares when it declares nothing: no default constructor,
/// no interface casts, no properties and an empty static constructor.
///
/// The class macros read the declarations of a type through the names below.
/// A type that declares one of them does so with an inherent item of the
/// same name (written by hand for [`static_constructor`](Self::static_constructor),
/// generated by [`ferro_properties!`](crate::ferro_properties) and
/// [`ferro_class_info!`] for the others), which takes precedence over this
/// trait; every other type falls back to it.
pub trait ClassDefaults {
    #[doc(hidden)]
    const __CONSTRUCTOR: Option<fn() -> Ref<FerroObject>> = None;

    #[doc(hidden)]
    const __INTERFACES: &'static [TypeOf] = &[];

    #[doc(hidden)]
    const __MARKUP: Option<&'static MarkupType> = None;

    #[doc(hidden)]
    #[inline]
    fn __register_interfaces() {}

    #[doc(hidden)]
    #[inline]
    fn __register_properties() {}

    /// The static constructor of a type: work done once per thread, after
    /// the properties of the type are registered and before its first
    /// instance exists (class handlers, `affects_render`, metadata
    /// overrides).
    ///
    /// A class declares it as an inherent function in the module of its
    /// `ferro_class!`:
    ///
    /// ```ignore
    /// impl Border {
    ///     fn static_constructor() {
    ///         Self::affects_render::<Border>(&[Self::background_property().as_property()]);
    ///     }
    /// }
    /// ```
    ///
    /// It is never called by hand: the class initialisation calls it. Use
    /// `Border::TYPE.ensure_class_init()` to force the initialisation.
    #[inline]
    fn static_constructor() {}
}

impl<T: ?Sized> ClassDefaults for T {}

/// The part of a class initialisation that is the same for every class:
/// makes the type known by name and registers its handle type `Ref<T>` with
/// the untyped value conversions (as an object handle that casts to the
/// handles of its base classes and to its nullable form). The conversions
/// are registered when the thread first uses untyped conversions.
#[doc(hidden)]
#[cold]
pub fn __register_class<T: ObjectType>() {
    TypeInfo::register(T::TYPE);
    crate::data::core::ValueTypes::register_deferred(crate::data::core::ValueTypes::register_object::<T>);
}

/// Access to the embedded base-class data of an object.
///
/// Implemented by [`ferro_class!`] for every ancestor of a class, so
/// `T: Upcast<U>` reads as "`T` is `U` or derives from it".
pub trait Upcast<T: ?Sized> {
    fn upcast(&self) -> &T;
}

/// Implemented by every class.
///
/// # Safety
///
/// Implemented only by [`ferro_class!`] (and by hand for the root class).
/// Implementors guarantee that:
///
/// * `Self` is `#[repr(C)]`-compatible with `Parent` at offset zero, i.e. a
///   pointer to `Self` is a valid pointer to every class in its ancestor
///   chain;
/// * `VTable` likewise starts with `Parent::VTable` at offset zero;
/// * values of `Self` are only created through [`instantiate`] (class structs
///   have a private `base` field and `construct`-style constructors that are
///   only meaningful inside `instantiate`).
pub unsafe trait ObjectType: StaticType + Upcast<FerroObject> + Sized {
    /// The base class. The root class is its own parent.
    type Parent: ObjectType;

    /// The virtual table of the class.
    type VTable: Copy + 'static;

    /// The virtual table used by instances whose most-derived class is `Self`.
    fn vtable() -> &'static Self::VTable;

    /// The static initialisation of the class. The first call on a thread,
    /// after doing the same for the base class:
    ///
    /// 1. makes the type known by name ([`TypeInfo::find`]);
    /// 2. registers the handle type `Ref<Self>` and the interface handles the
    ///    class declares ([`ferro_class_info!`]) with the untyped value
    ///    conversions;
    /// 3. registers the properties of the class in declaration order
    ///    ([`ferro_properties!`](crate::ferro_properties));
    /// 4. runs the static constructor of the class
    ///    ([`ClassDefaults::static_constructor`]).
    ///
    /// Later calls only read a thread-local flag.
    ///
    /// Generated by `ferro_class!`. Called by [`instantiate`], so a class
    /// that has an instance on the thread is initialised, and through
    /// [`TypeInfo::ensure_class_init`] by property accessors and the property
    /// registry, for classes that have none.
    fn register_class();
}

/// Implemented by a class `C` for every class `T` that can derive from it:
/// builds `C`'s part of the virtual table with `T`'s overrides.
pub trait Subclassable<T>: ObjectType {
    #[doc(hidden)]
    fn build_vtable() -> Self::VTable;
}

/// Reinterprets a reference to base class data as a reference to the derived
/// class `T`.
///
/// # Safety
///
/// `base` must be the base-class part of an object whose most-derived class
/// is `T` or derives from `T`.
#[doc(hidden)]
#[inline(always)]
pub unsafe fn cast_this<B, T>(base: &B) -> &T {
    &*(base as *const B as *const T)
}

/// Returns the virtual table of `T`'s parent class, viewed as the table type
/// `V` of the class that introduced the member being called.
///
/// Panics if the parent class has no `V`, i.e. when the class that introduced
/// a virtual member did not implement it itself.
#[doc(hidden)]
#[inline]
pub fn parent_vtable<T: ObjectType, V>() -> &'static V {
    // A parent class that is an ancestor of the class owning `V` has a
    // strictly smaller table (the owner adds at least the member being
    // called), so this check is exact. It is constant per instantiation.
    assert!(
        std::mem::size_of::<<T::Parent as ObjectType>::VTable>() >= std::mem::size_of::<V>(),
        "virtual member has no base implementation"
    );
    let table: *const <T::Parent as ObjectType>::VTable = <T::Parent as ObjectType>::vtable();
    // SAFETY: by the size argument above the parent class is the owner of `V`
    // or derives from it, and `ObjectType` guarantees that a class's table
    // starts with the tables of all of its ancestors.
    unsafe { &*(table as *const V) }
}

/// Whether the slot of `member` in the table of `T` takes the slot of the
/// table of `T`'s parent class, instead of a function of `T` that forwards
/// to it. `V` is the table of the class that introduced the member.
///
/// `overrides` is what the implementation of `T` states about itself
/// (`__OVERRIDES` of the implementation trait): `None` when it states
/// nothing, else the names of the members it overrides. A member that is
/// not among them has the default of the implementation trait, which calls
/// the same slot of the parent table and does nothing else, so the slot of
/// the parent is the same implementation with one call less.
///
/// The slot is not taken where the parent class has no table `V`: the class
/// that introduced a member has to implement it, and its default panics
/// when it is called (see [`parent_vtable`]), not when the table is built.
///
/// A constant function: the tables evaluate it when the class is compiled,
/// so a table is built without comparing names and the forwarding function
/// of a slot that is taken from the parent is not referenced.
#[doc(hidden)]
pub const fn __forwards_to_parent<T: ObjectType, V>(
    overrides: Option<&'static [&'static str]>,
    member: &str,
) -> bool {
    let overrides = match overrides {
        Some(overrides) => overrides,
        None => return false,
    };
    if std::mem::size_of::<<T::Parent as ObjectType>::VTable>() < std::mem::size_of::<V>() {
        return false;
    }
    let member = member.as_bytes();
    let mut index = 0;
    while index < overrides.len() {
        let name = overrides[index].as_bytes();
        if name.len() == member.len() {
            let mut at = 0;
            while at < name.len() && name[at] == member[at] {
                at += 1;
            }
            if at == name.len() {
                return false;
            }
        }
        index += 1;
    }
    true
}

/// A strong reference to an object of class `T` or a class derived from it.
///
/// Cloning the handle shares the object. Equality and hashing are by object
/// identity.
#[repr(transparent)]
pub struct Ref<T: ObjectType> {
    ptr: Rc<dyn Any>,
    _marker: PhantomData<T>,
}

impl<T: ObjectType> Ref<T> {
    /// Converts the handle to a handle of a base class.
    #[inline]
    pub fn upcast<U: ObjectType>(self) -> Ref<U>
    where
        T: Upcast<U>,
    {
        Ref { ptr: self.ptr, _marker: PhantomData }
    }

    /// Borrows the handle as a handle of a base class, without a copy of the
    /// handle (the borrowing form of [`upcast`](Self::upcast)).
    #[inline]
    pub fn upcast_ref<U: ObjectType>(&self) -> &Ref<U>
    where
        T: Upcast<U>,
    {
        // SAFETY: `Ref` is `repr(transparent)` over its `Rc<dyn Any>`; the
        // marker is zero-sized, so `Ref<T>` and `Ref<U>` have the same layout
        // and the same valid values, and `T: Upcast<U>` makes the object a `U`,
        // which is exactly what `upcast` asserts for an owned handle.
        unsafe { &*(self as *const Ref<T> as *const Ref<U>) }
    }

    /// Returns a handle of class `U` if the object is a `U`.
    #[inline]
    pub fn cast<U: ObjectType>(&self) -> Option<Ref<U>> {
        if self.is::<U>() {
            Some(Ref { ptr: self.ptr.clone(), _marker: PhantomData })
        } else {
            None
        }
    }

    /// Converts the handle to class `U` if the object is a `U`, otherwise
    /// returns the handle unchanged.
    #[inline]
    pub fn downcast<U: ObjectType>(self) -> Result<Ref<U>, Self> {
        if self.is::<U>() {
            Ok(Ref { ptr: self.ptr, _marker: PhantomData })
        } else {
            Err(self)
        }
    }

    /// Whether the object is of class `U` or a class derived from it.
    #[inline]
    pub fn is<U: ObjectType>(&self) -> bool {
        let object: &FerroObject = (**self).upcast();
        U::TYPE.is_assignable_from(object.get_type())
    }

    /// Creates a weak reference to the object.
    #[inline]
    pub fn downgrade(&self) -> WeakRef<T> {
        WeakRef::of(Rc::downgrade(&self.ptr))
    }

    /// Whether two handles refer to the same object.
    #[inline]
    pub fn ptr_eq<U: ObjectType>(&self, other: &Ref<U>) -> bool {
        std::ptr::addr_eq(Rc::as_ptr(&self.ptr), Rc::as_ptr(&other.ptr))
    }

    /// The number of handles to the object, the number of weak handles to it and its address:
    /// what a leak test says of an object that survived its scenario. For tests only.
    #[cfg(feature = "testing")]
    #[doc(hidden)]
    pub fn reference_counts(&self) -> (usize, usize, usize) {
        (Rc::strong_count(&self.ptr), Rc::weak_count(&self.ptr), Rc::as_ptr(&self.ptr) as *const () as usize)
    }

    #[inline]
    pub(crate) fn from_rc(ptr: Rc<dyn Any>) -> Self {
        Ref { ptr, _marker: PhantomData }
    }
}

impl<T: ObjectType> Deref for Ref<T> {
    type Target = T;

    #[inline]
    fn deref(&self) -> &T {
        // SAFETY: a `Ref<T>` is only created by `instantiate` (for the exact
        // class), by `upcast` (statically an ancestor) and by `cast` /
        // `downcast` / `FerroObject::to_ref` (after a runtime type check), so
        // the allocation holds an object whose class is `T` or derives from
        // it, and `ObjectType` guarantees `T` is at offset zero of it.
        unsafe { &*(Rc::as_ptr(&self.ptr) as *const T) }
    }
}

impl<T: ObjectType> Clone for Ref<T> {
    #[inline]
    fn clone(&self) -> Self {
        Ref { ptr: self.ptr.clone(), _marker: PhantomData }
    }
}

impl<T: ObjectType, U: ObjectType> PartialEq<Ref<U>> for Ref<T> {
    #[inline]
    fn eq(&self, other: &Ref<U>) -> bool {
        self.ptr_eq(other)
    }
}

impl<T: ObjectType> Eq for Ref<T> {}

impl<T: ObjectType> Hash for Ref<T> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        (Rc::as_ptr(&self.ptr) as *const () as usize).hash(state)
    }
}

impl<T: ObjectType> fmt::Debug for Ref<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let object: &FerroObject = (**self).upcast();
        fmt::Debug::fmt(object, f)
    }
}

/// The word that follows the pointer of every [`WeakRef`] in a build with the
/// feature `tagged-weak-references`: a reader of the memory of the process
/// (the allocation trace of the tests of the ControlCatalog) tells a weak
/// reference to an object from a strong one by it.
#[cfg(feature = "tagged-weak-references")]
pub const WEAK_REFERENCE_TAG: usize = 0x5745_414B_5245_4631_u64 as usize;

/// A weak reference to an object of class `T` or a class derived from it.
#[cfg_attr(feature = "tagged-weak-references", repr(C))]
pub struct WeakRef<T: ObjectType> {
    ptr: Weak<dyn Any>,
    #[cfg(feature = "tagged-weak-references")]
    tag: usize,
    _marker: PhantomData<T>,
}

impl<T: ObjectType> WeakRef<T> {
    #[inline]
    fn of(ptr: Weak<dyn Any>) -> Self {
        WeakRef {
            ptr,
            #[cfg(feature = "tagged-weak-references")]
            tag: WEAK_REFERENCE_TAG,
            _marker: PhantomData,
        }
    }
}

impl<T: ObjectType> WeakRef<T> {
    /// Returns a strong reference if the object is still alive.
    #[inline]
    pub fn upgrade(&self) -> Option<Ref<T>> {
        self.ptr.upgrade().map(|ptr| Ref { ptr, _marker: PhantomData })
    }

    /// Converts the handle to a handle of a base class.
    #[inline]
    pub fn upcast<U: ObjectType>(self) -> WeakRef<U>
    where
        T: Upcast<U>,
    {
        WeakRef::of(self.ptr)
    }

    /// Whether the weak reference points at `object`.
    #[inline]
    pub fn points_to<U: ObjectType>(&self, object: &Ref<U>) -> bool {
        std::ptr::addr_eq(self.ptr.as_ptr(), Rc::as_ptr(&object.ptr))
    }

    /// Whether the weak reference points at `object` (which, being borrowed, is alive).
    #[inline]
    pub(crate) fn points_at(&self, object: &T) -> bool {
        std::ptr::addr_eq(self.ptr.as_ptr(), object as *const T)
    }

    /// Whether two weak references point at the same object, alive or not.
    #[inline]
    pub fn ptr_eq<U: ObjectType>(&self, other: &WeakRef<U>) -> bool {
        std::ptr::addr_eq(self.ptr.as_ptr(), other.ptr.as_ptr())
    }

    #[inline]
    pub(crate) fn from_weak(ptr: Weak<dyn Any>) -> Self {
        WeakRef::of(ptr)
    }
}

impl<T: ObjectType> Clone for WeakRef<T> {
    #[inline]
    fn clone(&self) -> Self {
        WeakRef::of(self.ptr.clone())
    }
}

/// An optional object reference accepted by setters, convertible from a
/// handle (or a borrowed handle) of any derived class and from `None`.
pub struct Nullable<T: ObjectType>(pub Option<Ref<T>>);

impl<T: ObjectType + Upcast<U>, U: ObjectType> From<Ref<T>> for Nullable<U> {
    #[inline]
    fn from(value: Ref<T>) -> Self {
        Nullable(Some(value.upcast()))
    }
}

impl<T: ObjectType + Upcast<U>, U: ObjectType> From<&Ref<T>> for Nullable<U> {
    #[inline]
    fn from(value: &Ref<T>) -> Self {
        Nullable(Some(value.clone().upcast()))
    }
}

impl<U: ObjectType> From<Option<Ref<U>>> for Nullable<U> {
    #[inline]
    fn from(value: Option<Ref<U>>) -> Self {
        Nullable(value)
    }
}

/// A non-optional object reference accepted by methods, convertible from a
/// handle (or a borrowed handle) of any derived class.
pub trait IntoRef<U: ObjectType> {
    fn into_ref(self) -> Ref<U>;
}

impl<T: ObjectType + Upcast<U>, U: ObjectType> IntoRef<U> for Ref<T> {
    #[inline]
    fn into_ref(self) -> Ref<U> {
        self.upcast()
    }
}

impl<T: ObjectType + Upcast<U>, U: ObjectType> IntoRef<U> for &Ref<T> {
    #[inline]
    fn into_ref(self) -> Ref<U> {
        self.clone().upcast()
    }
}

/// Moves a constructed class value to the heap, attaches the virtual table of
/// its class and runs the `constructed` virtual member. The class (and its
/// base classes) are initialised first if this is the first instance on the
/// thread; see [`ObjectType::register_class`].
pub fn instantiate<T: ObjectType>(value: T) -> Ref<T> {
    T::register_class();
    let ptr: Rc<dyn Any> = Rc::new(value);
    let result: Ref<T> = Ref { ptr, _marker: PhantomData };
    let object: &FerroObject = (*result).upcast();
    let table: *const T::VTable = T::vtable();
    // SAFETY: `T::VTable` starts with the root class's table (`ObjectType`
    // invariant), and the object's most-derived class is `T`.
    unsafe { object.attach(Rc::downgrade(&result.ptr), table as *const ()) };
    object.constructed();
    result
}

/// Declares a class.
///
/// ```ignore
/// #[repr(C)]
/// pub struct Decorator { base: Control, /* fields */ }
///
/// // A class without new virtual members:
/// ferro_class!(Decorator: Control);
///
/// // A class that introduces virtual members:
/// ferro_class! {
///     Layoutable: Visual, virtuals LayoutableImpl: VisualImpl {
///         /// Measures the control.
///         fn measure_override(this, available_size: Size) -> Size;
///         fn arrange_override(this, final_size: Size) -> Size;
///     }
/// }
/// ```
///
/// Both forms generate `Deref<Target = Base>`, [`Upcast`] to every ancestor,
/// the `TYPE` runtime type and [`ObjectType`], including the static
/// initialisation of the class ([`ObjectType::register_class`]). What the
/// initialisation does is taken from the other declarations of the class,
/// each optional and found by the macro without being named here:
///
/// * `ferro_properties! { impl Decorator { .. } }`, the property definitions;
/// * `fn static_constructor()`, an inherent function declared in the same
///   module ([`ClassDefaults::static_constructor`]);
/// * `ferro_class_info!(Decorator { new: Decorator::new, interfaces: [..] })`,
///   the default constructor and the interface handles the class converts
///   to.
///
/// The second form also generates:
///
/// * `LayoutableVTable`, the table of the new members;
/// * `trait LayoutableImpl`, with one associated function per member taking
///   `this: &Self`. Every class deriving from `Layoutable` implements it
///   (`impl LayoutableImpl for Border {}`) and overrides what it needs
///   ([`ferro_impl_classes!`] and [`ferro_overrides!`] write the same
///   implementation and state what it overrides, which shortens the calls);
/// * `LayoutableImplExt::parent_<member>`, to call the base implementation
///   from an override;
/// * `Layoutable::<member>(&self, ..)`, which performs the virtual call.
///
/// The declaring class must implement every member itself; these are the
/// base implementations.
#[macro_export]
macro_rules! ferro_class {
    // What the type declares, in the order of a static initialisation:
    // interface casts, properties (field initialisers), static constructor.
    // Inherent items of the type win over the `ClassDefaults` fallbacks.
    (@class_members $name:ident) => {{
        #[allow(unused_imports)]
        use $crate::ClassDefaults as _;
        $crate::data::core::ValueTypes::register_deferred(<$name>::__register_interfaces);
        <$name>::__register_properties();
        <$name>::static_constructor();
    }};

    (@register_class $name:ident : $base:ident) => {
        #[inline]
        fn register_class() {
            $crate::ferro_thread_local! {
                static REGISTERED: ::std::cell::Cell<bool> = const { ::std::cell::Cell::new(false) };
            }
            #[cold]
            #[inline(never)]
            fn init() {
                <$base as $crate::ObjectType>::register_class();
                $crate::__register_class::<$name>();
                $crate::ferro_class!(@class_members $name);
            }
            if !REGISTERED.get() {
                // Set first: the initialisation may create instances of the
                // class or call its property accessors.
                REGISTERED.set(true);
                init();
            }
        }
    };

    (@common $name:ident : $base:ident) => {
        const _: () = assert!(
            ::std::mem::offset_of!($name, base) == 0,
            "class structs must be #[repr(C)] with `base` as their first field"
        );

        impl ::std::ops::Deref for $name {
            type Target = $base;
            #[inline]
            fn deref(&self) -> &$base {
                &self.base
            }
        }

        impl<T: ?Sized> $crate::Upcast<T> for $name
        where
            $base: $crate::Upcast<T>,
        {
            #[inline]
            fn upcast(&self) -> &T {
                $crate::Upcast::upcast(&self.base)
            }
        }

        impl $crate::Upcast<$name> for $name {
            #[inline]
            fn upcast(&self) -> &$name {
                self
            }
        }

        impl $crate::StaticType for $name {
            const TYPE: &'static $crate::TypeInfo = {
                static TYPE: $crate::TypeInfo = $crate::TypeInfo::new(
                    stringify!($name),
                    Some(<$base as $crate::StaticType>::TYPE),
                )
                .with_module_path(::std::module_path!())
                .with_class_init(<$name as $crate::ObjectType>::register_class)
                .with_constructor({
                    #[allow(unused_imports)]
                    use $crate::ClassDefaults as _;
                    <$name>::__CONSTRUCTOR
                })
                .with_handles(|| {
                    [
                        ::std::any::TypeId::of::<$crate::Ref<$name>>(),
                        ::std::any::TypeId::of::<::std::option::Option<$crate::Ref<$name>>>(),
                    ]
                })
                .with_handle_registration($crate::data::core::ValueTypes::register_object::<$name>)
                .with_interfaces({
                    #[allow(unused_imports)]
                    use $crate::ClassDefaults as _;
                    <$name>::__INTERFACES
                })
                .with_markup({
                    #[allow(unused_imports)]
                    use $crate::ClassDefaults as _;
                    <$name>::__MARKUP
                });
                &TYPE
            };
        }

        impl $name {
            /// The runtime type of this class.
            pub const TYPE: &'static $crate::TypeInfo = <$name as $crate::StaticType>::TYPE;

            /// Returns a strong reference to this object.
            #[inline]
            pub fn to_ref(&self) -> $crate::Ref<$name> {
                $crate::FerroObject::ref_of(self)
            }
        }
    };

    ($name:ident : $base:ident) => {
        $crate::ferro_class!(@common $name: $base);

        // SAFETY: the offset assertion above proves the layout requirement;
        // the table type is the parent's.
        unsafe impl $crate::ObjectType for $name {
            type Parent = $base;
            type VTable = <$base as $crate::ObjectType>::VTable;

            fn vtable() -> &'static Self::VTable {
                static VTABLE: ::std::sync::OnceLock<<$base as $crate::ObjectType>::VTable> =
                    ::std::sync::OnceLock::new();
                VTABLE.get_or_init(<$name as $crate::Subclassable<$name>>::build_vtable)
            }

            $crate::ferro_class!(@register_class $name: $base);
        }

        impl<T> $crate::Subclassable<T> for $name
        where
            $base: $crate::Subclassable<T>,
        {
            #[inline]
            fn build_vtable() -> Self::VTable {
                <$base as $crate::Subclassable<T>>::build_vtable()
            }
        }
    };

    (
        $name:ident : $base:ident, virtuals $impl_trait:ident : $parent_impl:path {
            $(
                $(#[$meta:meta])*
                fn $method:ident(this $(, $arg:ident : $arg_ty:ty)* $(,)?) $(-> $ret:ty)?;
            )*
        }
    ) => {
        $crate::ferro_class!(@common $name: $base);

        $crate::__paste! {
            /// The virtual table of the class.
            #[derive(Clone, Copy)]
            #[repr(C)]
            pub struct [<$name VTable>] {
                pub base: <$base as $crate::ObjectType>::VTable,
                $(pub $method: fn(&$name $(, $arg_ty)*) $(-> $ret)?,)*
            }

            // SAFETY: the offset assertion above proves the layout
            // requirement; the table is `#[repr(C)]` and starts with the
            // parent's table.
            unsafe impl $crate::ObjectType for $name {
                type Parent = $base;
                type VTable = [<$name VTable>];

                fn vtable() -> &'static Self::VTable {
                    static VTABLE: ::std::sync::OnceLock<[<$name VTable>]> = ::std::sync::OnceLock::new();
                    VTABLE.get_or_init(<$name as $crate::Subclassable<$name>>::build_vtable)
                }

                $crate::ferro_class!(@register_class $name: $base);
            }

            /// The overridable members introduced by the class.
            pub trait $impl_trait: $parent_impl + $crate::Upcast<$name> {
                /// The names of the members this implementation overrides,
                /// where it states them: `None` for an implementation
                /// written as a plain `impl`. Set by `ferro_impl_classes!`
                /// and `ferro_overrides!`, never by hand: the table of the
                /// class is built from it.
                #[doc(hidden)]
                const __OVERRIDES: ::std::option::Option<&'static [&'static str]> = ::std::option::Option::None;

                $(
                    $(#[$meta])*
                    #[allow(unused_variables)]
                    fn $method(this: &Self $(, $arg: $arg_ty)*) $(-> $ret)? {
                        <Self as [<$impl_trait Ext>]>::[<parent_ $method>](this $(, $arg)*)
                    }
                )*
            }

            /// Access to the base implementations of the overridable members.
            pub trait [<$impl_trait Ext>]: $impl_trait {
                $(
                    /// Calls the base class implementation of the member.
                    #[inline]
                    fn [<parent_ $method>](this: &Self $(, $arg: $arg_ty)*) $(-> $ret)? {
                        let table = $crate::parent_vtable::<Self, [<$name VTable>]>();
                        (table.$method)($crate::Upcast::<$name>::upcast(this) $(, $arg)*)
                    }
                )*
            }

            impl<T: $impl_trait> [<$impl_trait Ext>] for T {}

            impl<T: $impl_trait> $crate::Subclassable<T> for $name
            where
                $base: $crate::Subclassable<T>,
            {
                fn build_vtable() -> [<$name VTable>] {
                    [<$name VTable>] {
                        base: <$base as $crate::Subclassable<T>>::build_vtable(),
                        $(
                            $method: {
                                // SAFETY: this table is only attached to objects
                                // whose most-derived class is `T`.
                                let own: fn(&$name $(, $arg_ty)*) $(-> $ret)? =
                                    |this $(, $arg)*| T::$method(unsafe { $crate::cast_this::<$name, T>(this) } $(, $arg)*);
                                // A member `T` states it does not override is
                                // the default, which calls this slot of the
                                // parent table: the slot itself is taken.
                                let forwards: bool = const {
                                    $crate::__forwards_to_parent::<T, [<$name VTable>]>(
                                        <T as $impl_trait>::__OVERRIDES,
                                        ::std::stringify!($method),
                                    )
                                };
                                if forwards {
                                    $crate::parent_vtable::<T, [<$name VTable>]>().$method
                                } else {
                                    own
                                }
                            },
                        )*
                    }
                }
            }

            impl $name {
                $(
                    $(#[$meta])*
                    #[inline]
                    pub fn $method(&self $(, $arg: $arg_ty)*) $(-> $ret)? {
                        $crate::perf_count_virtual!(concat!(stringify!($name), "::", stringify!($method)));
                        let table = $crate::FerroObject::vtable_of::<$name>(self);
                        (table.$method)(self $(, $arg)*)
                    }
                )*
            }
        }
    };
}

/// Declares the facts about a class that untyped code (markup, untyped
/// bindings) needs and cannot derive: its default constructor, the
/// interface handles its handle converts to and its markup metadata. Every
/// part is optional; the parts may be written in any order.
///
/// ```ignore
/// ferro_class!(SolidColorBrush: Brush);
/// ferro_class_info!(SolidColorBrush {
///     new: SolidColorBrush::new,
///     interfaces: [Rc<dyn IBrush>],
/// });
///
/// ferro_class!(Panel: Control);
/// ferro_class_info!(Panel {
///     new: Panel::new,
///     markup: {
///         content: Children,
///         properties: [
///             Children: Rc<Controls> { get: Panel::children },
///         ],
///     },
/// });
/// ```
///
/// * `new` is a function without parameters that returns the handle of a new
///   instance. It becomes [`TypeInfo::default_constructor`].
/// * `interfaces` lists the handle types `I` that `Ref<Class>` converts to
///   with `Into<I>`, or, as `I => function`, with the given
///   `fn(Ref<Class>) -> I` (for an interface of another crate, for which
///   the conversion trait cannot be implemented). They are registered with the untyped value conversions
///   when the class is initialised, for the class and every class deriving
///   from it (a more derived class that lists the same interface takes
///   precedence for its own instances), and are listed by
///   [`TypeInfo::interfaces`].
/// * `markup` states what markup needs beyond the registered properties of
///   the class, which need no declaration: the content property, plain
///   (non-registered) properties and collections, constructors with
///   arguments, methods, static values, events and attributes. The parts are
///   the ones of [`ferro_markup_type!`](crate::ferro_markup_type) (without
///   `handles`, `this` and `base`, which follow from the class); instance
///   members are called with `&Ref<Class>`, so `Class::method` paths work as
///   callables. It becomes [`TypeInfo::markup`]: constant data that costs
///   nothing until it is read.
#[macro_export]
macro_rules! ferro_class_info {
    (@new $name:ident $constructor:expr) => {
        impl $name {
            #[doc(hidden)]
            pub const __CONSTRUCTOR: ::std::option::Option<fn() -> $crate::Ref<$crate::FerroObject>> =
                ::std::option::Option::Some(|| $crate::Ref::<$name>::upcast($constructor()));
        }
    };

    (@cast) => {
        |object| ::std::convert::Into::into(object)
    };

    (@cast $cast:expr) => {
        $cast
    };

    (@interfaces $name:ident [$($interface:ty $(=> $cast:expr)?),* $(,)?]) => {
        impl $name {
            #[doc(hidden)]
            pub const __INTERFACES: &'static [$crate::metadata::TypeOf] =
                &[$(|| $crate::data::core::ValueType::of::<$interface>()),*];

            #[doc(hidden)]
            pub fn __register_interfaces() {
                $(
                    $crate::data::core::ValueTypes::register_interface::<$name, $interface>(
                        $crate::ferro_class_info!(@cast $($cast)?),
                    );
                )*
            }
        }
    };

    (@markup $name:ident { $($body:tt)* }) => {
        impl $name {
            $crate::__ferro_markup_functions!($crate::__ferro_markup_fns!($crate::Ref<$name>, $crate::Ref<$name>; $($body)*););

            #[doc(hidden)]
            pub const __MARKUP: ::std::option::Option<&'static $crate::metadata::MarkupType> = {
                static MARKUP: $crate::metadata::MarkupType = {
                    #[allow(unused_mut)]
                    let mut markup = $crate::metadata::MarkupType::new(
                        ::std::stringify!($name),
                        $crate::metadata::MarkupTypeKind::Class,
                        ::std::module_path!(),
                    );
                    markup.handles = &[
                        || $crate::data::core::ValueType::of::<$crate::Ref<$name>>(),
                        || $crate::data::core::ValueType::of::<::std::option::Option<$crate::Ref<$name>>>(),
                    ];
                    markup.type_info = ::std::option::Option::Some(|| <$name as $crate::StaticType>::TYPE);
                    markup.interfaces = {
                        #[allow(unused_imports)]
                        use $crate::ClassDefaults as _;
                        <$name>::__INTERFACES
                    };
                    $crate::__ferro_compiler_metadata!(
                        markup.this = ::std::option::Option::Some(|| $crate::data::core::ValueType::of::<$crate::Ref<$name>>());
                        markup.value = ::std::option::Option::Some(|| $crate::data::core::ValueType::of::<$crate::Ref<$name>>());
                    );
                    $crate::__ferro_markup_items!(markup, $crate::Ref<$name>; $($body)*);
                    markup
                };
                ::std::option::Option::Some(&MARKUP)
            };
        }
    };

    (@parts $name:ident;) => {};

    (@parts $name:ident; new: $constructor:expr $(, $($rest:tt)*)?) => {
        $crate::ferro_class_info!(@new $name $constructor);
        $crate::ferro_class_info!(@parts $name; $($($rest)*)?);
    };

    (@parts $name:ident; interfaces: $interfaces:tt $(, $($rest:tt)*)?) => {
        $crate::ferro_class_info!(@interfaces $name $interfaces);
        $crate::ferro_class_info!(@parts $name; $($($rest)*)?);
    };

    (@parts $name:ident; markup: $markup:tt $(, $($rest:tt)*)?) => {
        $crate::ferro_class_info!(@markup $name $markup);
        $crate::ferro_class_info!(@parts $name; $($($rest)*)?);
    };

    ($name:ident { $($parts:tt)* }) => {
        $crate::ferro_class_info!(@parts $name; $($parts)*);
    };
}

/// Declares the runtime type of a type that is not a class: a type that
/// owns attached properties and cannot be instantiated as an object.
///
/// ```ignore
/// pub struct KeyboardNavigation;
/// ferro_static_type!(KeyboardNavigation);
///
/// ferro_properties! {
///     impl KeyboardNavigation {
///         pub fn tab_index_property() -> AttachedProperty<i32> { .. }
///     }
/// }
/// ```
///
/// Unlike a hand-written `impl StaticType`, the runtime type carries the
/// static initialisation of the type (its `ferro_properties!` block and its
/// `fn static_constructor()`, as for a class), so its properties are found
/// by owner type and name before any accessor was called, and it knows its
/// module, hence its namespace.
#[macro_export]
macro_rules! ferro_static_type {
    ($name:ident) => {
        impl $crate::StaticType for $name {
            const TYPE: &'static $crate::TypeInfo = {
                fn class_init() {
                    $crate::ferro_thread_local! {
                        static REGISTERED: ::std::cell::Cell<bool> = const { ::std::cell::Cell::new(false) };
                    }
                    if !REGISTERED.replace(true) {
                        $crate::TypeInfo::register(<$name as $crate::StaticType>::TYPE);
                        $crate::ferro_class!(@class_members $name);
                    }
                }
                static TYPE: $crate::TypeInfo = $crate::TypeInfo::new(stringify!($name), None)
                    .with_module_path(::std::module_path!())
                    .with_class_init(class_init);
                &TYPE
            };
        }

        impl $name {
            /// The runtime type of this type.
            #[allow(dead_code)]
            pub const TYPE: &'static $crate::TypeInfo = <$name as $crate::StaticType>::TYPE;
        }
    };
}

/// Implements class `Impl` traits with no overrides.
///
/// ```ignore
/// ferro_impl_classes!(Border: FerroObjectImpl, StyledElementImpl, VisualImpl);
/// ```
///
/// Unlike `impl VisualImpl for Border {}`, which means the same, this form
/// states that nothing is overridden, and the table of the class is built
/// from that: every slot of the members of these traits is the slot of the
/// base class, so a call reaches the implementation without passing through
/// a forwarding function of this class.
#[macro_export]
macro_rules! ferro_impl_classes {
    ($name:ty : $($trait_:path),+ $(,)?) => {
        $(
            impl $trait_ for $name {
                const __OVERRIDES: ::std::option::Option<&'static [&'static str]> = ::std::option::Option::Some(&[]);
            }
        )+
    };
}

/// Implements a class `Impl` trait and states which of its members the
/// implementation overrides: the ones written in the block.
///
/// ```ignore
/// ferro_overrides! { impl FerroObjectImpl for Border {
///     fn on_property_changed(this: &Self, change: &FerroPropertyChangedEventArgs<'_>) {
///         Self::parent_on_property_changed(this, change);
///         // ..
///     }
/// } }
/// ```
///
/// The implementation is the one a plain `impl FerroObjectImpl for Border`
/// with the same functions gives. What the macro adds is the list of their
/// names, from which the table of the class is built: the slot of a member
/// that is not in the block is the slot of the base class, so a call of it
/// reaches the implementation without passing through a forwarding function
/// of this class. The list is taken from the functions themselves and cannot
/// differ from them.
///
/// The block holds functions only, each with its attributes and
/// documentation, as the members of an `Impl` trait are.
#[macro_export]
macro_rules! ferro_overrides {
    (
        impl $trait_:ident for $name:ident {
            $(
                $(#[$meta:meta])*
                fn $method:ident ( $($params:tt)* ) $(-> $ret:ty)? $body:block
            )*
        }
    ) => {
        impl $trait_ for $name {
            const __OVERRIDES: ::std::option::Option<&'static [&'static str]> =
                ::std::option::Option::Some(&[$(::std::stringify!($method)),*]);

            $(
                $(#[$meta])*
                fn $method($($params)*) $(-> $ret)? $body
            )*
        }
    };
}