Skip to main content

ferroui_base/metadata/
markup_macros.rs

1//! The declaration forms of markup metadata.
2//!
3//! The grammar is deliberately rigid: the same declarations are read by the
4//! compiler (expanded into constant [`MarkupType`](super::MarkupType) data)
5//! and, syntactically, by build tooling.
6
7/// Declares the markup metadata of a type that is not a class of the object
8/// model: a value type, a plain shared (reference) type, a contract, or a
9/// type of another crate. (Classes state theirs in the `markup` part of
10/// [`ferro_class_info!`](crate::ferro_class_info); enumerations use
11/// [`ferro_markup_enum!`](crate::ferro_markup_enum).)
12///
13/// ```ignore
14/// ferro_markup_type!(struct Thickness {
15///     handles: [Thickness],
16///     parse: Thickness::parse,
17///     constructors: [
18///         (f64) => Thickness::uniform,
19///         (f64, f64, f64, f64) => Thickness::new,
20///     ],
21///     properties: [
22///         Left: f64 { get: |t: &Thickness| t.left },
23///     ],
24/// });
25///
26/// ferro_markup_type!(class Setter {
27///     handles: [Setter, Rc<Setter>, Option<Rc<Setter>>],
28///     this: Rc<Setter>,
29///     interfaces: [Rc<dyn ISetter>],
30///     constructors: [() => Setter::empty],
31///     content: Value,
32///     properties: [
33///         Property: Option<&'static FerroProperty> { get: Setter::property, set: Setter::set_property },
34///         Value: Option<BoxedValue> { get: Setter::value, set: Setter::set_value }
35///             [AssignBinding, DependsOn("Property")],
36///     ],
37/// });
38///
39/// ferro_markup_type!(interface dyn IBrush as "IBrush" {
40///     handles: [Rc<dyn IBrush>, Option<Rc<dyn IBrush>>],
41/// });
42/// ```
43///
44/// The head is `class`, `struct`, `interface` or `static`, the Rust type
45/// and, when the markup name is not the identifier of the type, `as "Name"`.
46/// It implements [`MarkupTyped`](super::MarkupTyped) for the type. The body
47/// is a list of the parts below, each optional, in any order:
48///
49/// * `namespace: "System"` — the dotted namespace, when it differs from the
50///   one registered for the declaring module.
51/// * `handles: [T, ..]` — the Rust types that hold values of the type, the
52///   untyped form first (see [`MarkupType::handles`](super::MarkupType::handles)).
53///   For a `struct` (and an enumeration) the nullable form `Option<T>` is
54///   recorded automatically as [`MarkupType::nullable`](super::MarkupType::nullable).
55/// * `this: T` — the type instance members receive (`&T`); by default the
56///   declared type itself. May be written anywhere in the list. A callable written `Type::method` works for any
57///   handle that dereferences to `Type`.
58/// * `base: T` and `interfaces: [T, ..]` — the base type and the contracts,
59///   by handle.
60/// * `generic: "FerroList`1" [T]` — the generic definition this type
61///   instantiates and its arguments.
62/// * `content: Name` — the content property.
63/// * `parse: path` — a function `fn(&str) -> Result<T, E>`: the `Parse(string)`
64///   of the type.
65/// * `constructors: [(A, B) => callable, ..]` — the positional form; a
66///   constructor whose parameters carry names or attributes in the managed
67///   original names them all: `(property: &'static FerroProperty [InheritDataTypeFrom(2)], mode: BindingMode) => callable`
68///   ([`MarkupConstructor::parameter_info`](super::MarkupConstructor::parameter_info)).
69/// * `properties: [Name: T { get: callable, set: callable } [Attribute(..), ..], ..]`
70///   — `get` is called with `(&this)`, `set` with `(&this, value: T)`;
71///   either may be omitted, the attribute list too.
72/// * `indexers: [(i32) -> T { get: callable, set: callable }, (String) -> T { get: callable }]`
73///   — the indexers (`this[..]`): `get` is called with `(&this, index..)`,
74///   `set` with `(&this, index.., value: T)`; either may be omitted, an
75///   attribute list may follow. Binding paths use them for `Path[0]` and
76///   `Path[key]`.
77/// * `property_attributes: [Name: [Attribute(..), ..], ..]` — attributes of
78///   REGISTERED properties (which are otherwise not declared at all).
79/// * `notify_property_changed: T` — the type raises property change
80///   notifications: `T` is the Rust type of its untyped form (the first
81///   handle) and implements `INotifyPropertyChanged`. Bindings resolved
82///   through metadata subscribe through it, for a value held as `T` (the
83///   box is the shared object) or as `Rc<T>`.
84/// * `type_info: X` — for a `static` type declared with
85///   [`ferro_static_type!`](crate::ferro_static_type): links the metadata to
86///   its runtime type (found with `MarkupType::find_by_type_info`).
87/// * `methods: [fn Name(A, B) -> R => callable, static fn Name(A) => callable, ..]`
88///   — an instance method is called with `(&this, a, b)`. An attribute list
89///   may follow the callable (`fn CanSave(Option<BoxedValue>) -> bool => Vm::can_save [DependsOn("Name")]`);
90///   the callable is then a plain path (`Type::method`), or any expression in parentheses
91///   (`=> (|this: &Rc<Vm>, p| this.can_save(p)) [DependsOn("Name")]`). A
92///   callable that is a path is never an index expression.
93/// * `fields: [Name: T => callable, ..]` — static FIELDS and constants
94///   (`static readonly` / `const` of the managed original), read with `()`.
95/// * `static_properties: [Name: T { get: callable, set: callable } [Attribute(..)], ..]`
96///   — static PROPERTIES (`static T Name { get; set; }`): `get` is called
97///   with `()`, `set` with `(value: T)`; `try_get:` / `try_set:` as for
98///   instance properties.
99/// * `events: [Name(A, B) => callable, ..]` — the callable subscribes a
100///   handler: it is called with `(&this, MarkupDelegate)`. The listed types
101///   are the parameters of the handler as the managed original declares
102///   them and the delegate is invoked with exactly that many untyped
103///   values: `Name(Option<BoxedValue>, EventArgs)` for an
104///   `EventHandler<EventArgs>` (the adapter passes the instance as sender
105///   when the Rust event has none), `Name()` for an event without
106///   arguments.
107/// * `attributes: [Name, Name("text", 1, true, type(T), Key = value), ..]`
108///   — type attributes; arguments are literals (text, integers, floating
109///   point numbers, booleans, characters), `null`, `type(T)` or an array of
110///   those (`Name(["a", "b"])`, `Separators = [",", " "]`; arrays nest).
111///
112/// **Fallible members.** A member whose callable returns `Result<T, E>`
113/// (`E: Display`) is declared with `try`: `try fn Name(A) -> T => callable`,
114/// `static try fn ..`, `try (A) => callable` for a constructor,
115/// `try_get:` / `try_set:` for property and indexer accessors and `try Name(A) => callable`
116/// for an event subscription. `Err` becomes
117/// [`MarkupInvokeError::Failed`](super::MarkupInvokeError::Failed) (the
118/// exception of the managed original); the declared types are the `Ok`
119/// types.
120///
121/// Callables are paths or closures; parameter and property types are the
122/// exact Rust types the callable takes and returns.
123#[macro_export]
124macro_rules! ferro_markup_type {
125    // A contract (`dyn Trait`): without a `this:` part its instance members
126    // receive the unsized trait object, which has no value type of its own.
127    ($kind:ident dyn $trait_:path as $name:literal { $($body:tt)* }) => {
128        $crate::ferro_markup_type!(@impl $kind dyn $trait_, $name, implied_dyn, { $($body)* });
129    };
130    ($kind:ident $type_:ty { $($body:tt)* }) => {
131        $crate::ferro_markup_type!(@impl $kind $type_, ::std::stringify!($type_), implied, { $($body)* });
132    };
133    ($kind:ident $type_:ty as $name:literal { $($body:tt)* }) => {
134        $crate::ferro_markup_type!(@impl $kind $type_, $name, implied, { $($body)* });
135    };
136
137    (@nullable struct $m:ident, $type_:ty) => {
138        $m.nullable = ::std::option::Option::Some(|| {
139            $crate::data::core::ValueType::of::<::std::option::Option<$type_>>()
140        });
141    };
142    (@nullable $kind:ident $m:ident, $type_:ty) => {};
143
144    (@kind class) => { $crate::metadata::MarkupTypeKind::Class };
145    (@kind struct) => { $crate::metadata::MarkupTypeKind::Struct };
146    (@kind interface) => { $crate::metadata::MarkupTypeKind::Interface };
147    (@kind static) => { $crate::metadata::MarkupTypeKind::Static };
148
149    (@this $kind:ident implied_dyn $m:ident, $this:ty) => {};
150    (@this $kind:ident $form:ident $m:ident, $this:ty) => {
151        $m.this = ::std::option::Option::Some(|| $crate::data::core::ValueType::of::<$this>());
152    };
153
154    // The typed functions of the members, as associated functions of the type, and
155    // the value type of the type: what a constructor and `Parse` return. It is the
156    // instance type when the declaration states `this:`, else the first of its
157    // `handles:` (the untyped form), else the declared type (`Rc<dyn Trait>` for a
158    // contract).
159    (@fns explicit $type_:ty, $this:ty; $($body:tt)*) => {
160        $crate::ferro_markup_type!(@fns_impl $type_, $this, $this; $($body)*);
161    };
162    (@fns $form:ident $type_:ty, $this:ty; $($body:tt)*) => {
163        $crate::ferro_markup_type!(@fns_value $form $type_, $this, [$($body)*] $($body)*);
164    };
165    (@fns_value $form:ident $type_:ty, $this:ty, [$($all:tt)*] handles: [$first:ty $(, $more:ty)* $(,)?] $($rest:tt)*) => {
166        $crate::ferro_markup_type!(@fns_impl $type_, $this, $first; $($all)*);
167    };
168    (@fns_value $form:ident $type_:ty, $this:ty, [$($all:tt)*] $next:tt $($rest:tt)*) => {
169        $crate::ferro_markup_type!(@fns_value $form $type_, $this, [$($all)*] $($rest)*);
170    };
171    (@fns_value implied_dyn $type_:ty, $this:ty, [$($all:tt)*]) => {
172        $crate::ferro_markup_type!(@fns_impl $type_, $this, ::std::rc::Rc<$type_>; $($all)*);
173    };
174    (@fns_value $form:ident $type_:ty, $this:ty, [$($all:tt)*]) => {
175        $crate::ferro_markup_type!(@fns_impl $type_, $this, $this; $($all)*);
176    };
177    (@fns_impl $type_:ty, $this:ty, $value:ty; $($body:tt)*) => {
178        impl $type_ {
179            /// The value type of the type (`MarkupType::value`).
180            #[doc(hidden)]
181            pub const __MARKUP_VALUE: $crate::metadata::TypeOf = || $crate::data::core::ValueType::of::<$value>();
182
183            $crate::__ferro_markup_fns!($this, $value; $($body)*);
184        }
185    };
186
187    (@build $kind:ident $type_:ty, $name:expr, $this:ty, $form:ident, { $($body:tt)* }) => {
188        $crate::__ferro_markup_functions!($crate::ferro_markup_type!(@fns $form $type_, $this; $($body)*););
189
190        impl $crate::metadata::MarkupTyped for $type_ {
191            const MARKUP: &'static $crate::metadata::MarkupType = {
192                static MARKUP: $crate::metadata::MarkupType = {
193                    #[allow(unused_mut)]
194                    let mut markup = $crate::metadata::MarkupType::new(
195                        $name,
196                        $crate::ferro_markup_type!(@kind $kind),
197                        ::std::module_path!(),
198                    );
199                    $crate::ferro_markup_type!(@nullable $kind markup, $type_);
200                    $crate::__ferro_compiler_metadata!(
201                        $crate::ferro_markup_type!(@this $kind $form markup, $this);
202                        markup.value = ::std::option::Option::Some(<$type_>::__MARKUP_VALUE);
203                    );
204                    $crate::__ferro_markup_items!(markup, $this; $($body)*);
205                    markup
206                };
207                &MARKUP
208            };
209        }
210    };
211    // Finds the `this:` part, wherever it is written; the declared type is
212    // the default.
213    (@scan $kind:ident $type_:ty, $name:expr, $default:ident, [$($seen:tt)*] this: $this:ty, $($rest:tt)*) => {
214        $crate::ferro_markup_type!(@build $kind $type_, $name, $this, explicit, { $($seen)* $($rest)* });
215    };
216    (@scan $kind:ident $type_:ty, $name:expr, $default:ident, [$($seen:tt)*] this: $this:ty) => {
217        $crate::ferro_markup_type!(@build $kind $type_, $name, $this, explicit, { $($seen)* });
218    };
219    (@scan $kind:ident $type_:ty, $name:expr, $default:ident, [$($seen:tt)*] $next:tt $($rest:tt)*) => {
220        $crate::ferro_markup_type!(@scan $kind $type_, $name, $default, [$($seen)* $next] $($rest)*);
221    };
222    (@scan $kind:ident $type_:ty, $name:expr, $default:ident, [$($seen:tt)*]) => {
223        $crate::ferro_markup_type!(@build $kind $type_, $name, $type_, $default, { $($seen)* });
224    };
225    (@impl $kind:ident $type_:ty, $name:expr, $default:ident, { $($body:tt)* }) => {
226        $crate::ferro_markup_type!(@scan $kind $type_, $name, $default, [] $($body)*);
227    };
228}
229
230/// Declares the markup metadata of an enumeration: its members by name.
231///
232/// ```ignore
233/// ferro_markup_enum!(Dock { Left, Bottom, Right, Top });
234///
235/// // A member whose Rust variant has another name (`Self` is reserved):
236/// ferro_markup_enum!(RelativeSourceMode { DataContext, TemplatedParent, Self = Self_, FindAncestor });
237///
238/// // A set of flags (a `bitflags!` type): members name their constants.
239/// ferro_markup_enum!(flags RoutingStrategies {
240///     Direct = RoutingStrategies::DIRECT,
241///     Tunnel = RoutingStrategies::TUNNEL,
242///     Bubble = RoutingStrategies::BUBBLE,
243/// });
244///
245/// // With attributes or another namespace:
246/// ferro_markup_enum!(Dock { Left, Bottom, Right, Top }, { namespace: "FerroUI.Controls" });
247/// ```
248///
249/// The members of a plain enumeration are its variants (their numeric value
250/// is the discriminant); the members of a flags type are constants with a
251/// `bits()` method. The untyped form of a member is a value of the type
252/// itself. Implements [`MarkupTyped`](super::MarkupTyped).
253#[macro_export]
254macro_rules! ferro_markup_enum {
255    ($type_:ident { $($member:ident $(= $variant:ident)?),* $(,)? } $(, { $($body:tt)* })?) => {
256        impl $crate::metadata::MarkupTyped for $type_ {
257            const MARKUP: &'static $crate::metadata::MarkupType = {
258                static MARKUP: $crate::metadata::MarkupType = {
259                    #[allow(unused_mut)]
260                    let mut markup = $crate::metadata::MarkupType::new(
261                        ::std::stringify!($type_),
262                        $crate::metadata::MarkupTypeKind::Enum,
263                        ::std::module_path!(),
264                    );
265                    markup.handles = &[|| $crate::data::core::ValueType::of::<$type_>()];
266                    markup.nullable = ::std::option::Option::Some(|| {
267                        $crate::data::core::ValueType::of::<::std::option::Option<$type_>>()
268                    });
269                    markup.enum_members = &[
270                        $($crate::metadata::MarkupEnumMember {
271                            name: ::std::stringify!($member),
272                            value: $crate::__ferro_markup_enum_variant!($type_, $member $(, $variant)?) as i64,
273                            get: || ::std::rc::Rc::new($crate::__ferro_markup_enum_variant!($type_, $member $(, $variant)?)),
274                            rust_variant: ::std::option::Option::Some(
275                                $crate::__ferro_markup_enum_variant_name!($member $(, $variant)?),
276                            ),
277                        },)*
278                    ];
279                    markup.enum_from_value = ::std::option::Option::Some(|value| {
280                        $(
281                            if value == $crate::__ferro_markup_enum_variant!($type_, $member $(, $variant)?) as i64 {
282                                return ::std::option::Option::Some(::std::rc::Rc::new(
283                                    $crate::__ferro_markup_enum_variant!($type_, $member $(, $variant)?),
284                                ) as $crate::BoxedValue);
285                            }
286                        )*
287                        ::std::option::Option::None
288                    });
289                    markup.enum_to_value = ::std::option::Option::Some(|value| {
290                        value.downcast_ref::<$type_>().map(|value| ::std::clone::Clone::clone(value) as i64)
291                    });
292                    $($crate::__ferro_markup_items!(markup, $type_; $($body)*);)?
293                    markup
294                };
295                &MARKUP
296            };
297        }
298    };
299    (flags $type_:ident { $($member:ident = $value:expr),* $(,)? } $(, { $($body:tt)* })?) => {
300        impl $crate::metadata::MarkupTyped for $type_ {
301            const MARKUP: &'static $crate::metadata::MarkupType = {
302                static MARKUP: $crate::metadata::MarkupType = {
303                    #[allow(unused_mut)]
304                    let mut markup = $crate::metadata::MarkupType::new(
305                        ::std::stringify!($type_),
306                        $crate::metadata::MarkupTypeKind::Enum,
307                        ::std::module_path!(),
308                    );
309                    markup.is_flags = true;
310                    markup.handles = &[|| $crate::data::core::ValueType::of::<$type_>()];
311                    markup.nullable = ::std::option::Option::Some(|| {
312                        $crate::data::core::ValueType::of::<::std::option::Option<$type_>>()
313                    });
314                    markup.enum_members = &[
315                        $($crate::metadata::MarkupEnumMember {
316                            name: ::std::stringify!($member),
317                            value: $value.bits() as i64,
318                            get: || ::std::rc::Rc::new($value),
319                            rust_variant: ::std::option::Option::None,
320                        },)*
321                    ];
322                    markup.enum_from_value = ::std::option::Option::Some(|value| {
323                        #[allow(unused_mut)]
324                        let mut result = $type_::empty();
325                        #[allow(unused_mut)]
326                        let mut rest = value;
327                        $(
328                            {
329                                let bits = $value.bits() as i64;
330                                if value & bits == bits {
331                                    result = result | $value;
332                                    rest &= !bits;
333                                }
334                            }
335                        )*
336                        if rest != 0 {
337                            return ::std::option::Option::None;
338                        }
339                        ::std::option::Option::Some(::std::rc::Rc::new(result) as $crate::BoxedValue)
340                    });
341                    markup.enum_to_value = ::std::option::Option::Some(|value| {
342                        value.downcast_ref::<$type_>().map(|value| value.bits() as i64)
343                    });
344                    $($crate::__ferro_markup_items!(markup, $type_; $($body)*);)?
345                    markup
346                };
347                &MARKUP
348            };
349        }
350
351        $crate::__ferro_markup_functions!(impl $type_ {
352            /// The typed function of a value of the flags from its integer value
353            /// (see `MarkupEmit`): the members whose bits are all set, combined. The
354            /// emitter of Rust source writes it for a value made of members only.
355            #[doc(hidden)]
356            #[allow(clippy::all)]
357            pub fn __markup_flags(value: i64) -> Self {
358                #[allow(unused_mut)]
359                let mut result = $type_::empty();
360                $(
361                    {
362                        let bits = $value.bits() as i64;
363                        if value & bits == bits {
364                            result = result | $value;
365                        }
366                    }
367                )*
368                result
369            }
370        });
371    };
372}
373
374/// The parts of a metadata declaration, as assignments to the fields of the
375/// `MarkupType` under construction.
376#[doc(hidden)]
377#[macro_export]
378macro_rules! __ferro_markup_items {
379    ($m:ident, $this:ty; ) => {};
380
381    ($m:ident, $this:ty; namespace: $namespace:literal $(, $($rest:tt)*)?) => {
382        $m.explicit_namespace = ::std::option::Option::Some($namespace);
383        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
384    };
385
386    ($m:ident, $this:ty; handles: [$($handle:ty),* $(,)?] $(, $($rest:tt)*)?) => {
387        $m.handles = &[$(|| $crate::data::core::ValueType::of::<$handle>()),*];
388        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
389    };
390
391    ($m:ident, $this:ty; base: $base:ty $(, $($rest:tt)*)?) => {
392        $m.base = ::std::option::Option::Some(|| $crate::data::core::ValueType::of::<$base>());
393        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
394    };
395
396    ($m:ident, $this:ty; interfaces: [$($interface:ty),* $(,)?] $(, $($rest:tt)*)?) => {
397        $m.interfaces = &[$(|| $crate::data::core::ValueType::of::<$interface>()),*];
398        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
399    };
400
401    ($m:ident, $this:ty; generic: $definition:literal [$($argument:ty),* $(,)?] $(, $($rest:tt)*)?) => {
402        $m.generic = ::std::option::Option::Some($crate::metadata::MarkupGeneric {
403            definition: $definition,
404            arguments: &[$(|| $crate::data::core::ValueType::of::<$argument>()),*],
405        });
406        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
407    };
408
409    ($m:ident, $this:ty; content: $content:ident $(, $($rest:tt)*)?) => {
410        $m.content_property = ::std::option::Option::Some(::std::stringify!($content));
411        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
412    };
413
414    ($m:ident, $this:ty; attributes: [$($attributes:tt)*] $(, $($rest:tt)*)?) => {
415        $m.attributes = $crate::__ferro_markup_attributes!([] $($attributes)*);
416        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
417    };
418
419    ($m:ident, $this:ty; constructors: [$($constructors:tt)*] $(, $($rest:tt)*)?) => {
420        $m.constructors = $crate::__ferro_markup_pool!(constructors { [] $($constructors)* });
421        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
422    };
423
424    ($m:ident, $this:ty; parse: $parse:expr $(, $($rest:tt)*)?) => {
425        $m.parse = ::std::option::Option::Some(|arguments| {
426            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 1)?;
427            let text = arguments.next::<::std::string::String>()?;
428            match ($parse)(text.as_str()) {
429                ::std::result::Result::Ok(value) => {
430                    ::std::result::Result::Ok($crate::metadata::into_markup_value(value))
431                }
432                ::std::result::Result::Err(error) => ::std::result::Result::Err(
433                    $crate::metadata::MarkupInvokeError::Failed(::std::string::ToString::to_string(&error)),
434                ),
435            }
436        });
437        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
438    };
439
440    ($m:ident, $this:ty; properties: [
441        $($name:ident : $type_:ty { $($accessors:tt)* } $([$($attributes:tt)*])?),* $(,)?
442    ] $(, $($rest:tt)*)?) => {
443        $m.properties = &[
444            $($crate::metadata::MarkupProperty {
445                name: ::std::stringify!($name),
446                type_: || $crate::data::core::ValueType::of::<$type_>(),
447                get: $crate::__ferro_markup_getter!($this, $type_; $($accessors)*),
448                set: $crate::__ferro_markup_setter!($this, $type_; $($accessors)*),
449                attributes: $crate::__ferro_markup_attributes!([] $($($attributes)*)?),
450                typed_path_element: $crate::__ferro_markup_typed_path!(
451                    $this, $type_, ::std::stringify!($name); [] [] $($accessors)*
452                ),
453                emit_get: $crate::__ferro_compiler_metadata!(@value $crate::__ferro_markup_emit_accessor!(get $name; $($accessors)*)),
454                emit_set: $crate::__ferro_compiler_metadata!(@value $crate::__ferro_markup_emit_accessor!(set $name; $($accessors)*)),
455            },)*
456        ];
457        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
458    };
459
460    ($m:ident, $this:ty; indexers: [$($indexers:tt)*] $(, $($rest:tt)*)?) => {
461        $m.indexers = $crate::__ferro_markup_indexers!($this; [] $($indexers)*);
462        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
463    };
464
465    ($m:ident, $this:ty; property_attributes: [
466        $($name:ident : [$($attributes:tt)*]),* $(,)?
467    ] $(, $($rest:tt)*)?) => {
468        $m.property_attributes = &[
469            $((::std::stringify!($name), $crate::__ferro_markup_attributes!([] $($attributes)*)),)*
470        ];
471        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
472    };
473
474    ($m:ident, $this:ty; notify_property_changed: $object:ty $(, $($rest:tt)*)?) => {
475        $m.notify_property_changed = ::std::option::Option::Some(|value| {
476            // The object itself (the box is the shared object) or its handle.
477            match value.downcast_ref::<$object>() {
478                ::std::option::Option::Some(object) => ::std::option::Option::Some(
479                    object as &dyn $crate::data::model::INotifyPropertyChanged,
480                ),
481                ::std::option::Option::None => value
482                    .downcast_ref::<::std::rc::Rc<$object>>()
483                    .map(|object| &**object as &dyn $crate::data::model::INotifyPropertyChanged),
484            }
485        });
486        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
487    };
488
489    ($m:ident, $this:ty; type_info: $type_info:ty $(, $($rest:tt)*)?) => {
490        $m.type_info = ::std::option::Option::Some(|| <$type_info as $crate::StaticType>::TYPE);
491        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
492    };
493
494    ($m:ident, $this:ty; methods: [$($methods:tt)*] $(, $($rest:tt)*)?) => {
495        $m.methods = $crate::__ferro_markup_pool!(methods { $this; [] $($methods)* });
496        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
497    };
498
499    ($m:ident, $this:ty; fields: [$($name:ident : $type_:ty => $get:expr),* $(,)?] $(, $($rest:tt)*)?) => {
500        $m.fields = &[
501            $($crate::metadata::MarkupField {
502                name: ::std::stringify!($name),
503                type_: || $crate::data::core::ValueType::of::<$type_>(),
504                get: || $crate::metadata::into_markup_value::<$type_>(($get)()),
505                attributes: &[],
506                emit: $crate::__ferro_compiler_metadata!(@value ::std::option::Option::Some($crate::metadata::MarkupEmit {
507                    function: ::std::concat!("__markup_field_", ::std::stringify!($name)),
508                    fallible: false,
509                })),
510            },)*
511        ];
512        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
513    };
514
515    ($m:ident, $this:ty; static_properties: [
516        $($name:ident : $type_:ty { $($accessors:tt)* } $([$($attributes:tt)*])?),* $(,)?
517    ] $(, $($rest:tt)*)?) => {
518        $m.static_properties = &[
519            $($crate::metadata::MarkupProperty {
520                name: ::std::stringify!($name),
521                type_: || $crate::data::core::ValueType::of::<$type_>(),
522                get: $crate::__ferro_markup_static_getter!($type_; $($accessors)*),
523                set: $crate::__ferro_markup_static_setter!($type_; $($accessors)*),
524                attributes: $crate::__ferro_markup_attributes!([] $($($attributes)*)?),
525                typed_path_element: ::std::option::Option::None,
526                emit_get: $crate::__ferro_compiler_metadata!(@value $crate::__ferro_markup_emit_accessor!(static_get $name; $($accessors)*)),
527                emit_set: $crate::__ferro_compiler_metadata!(@value $crate::__ferro_markup_emit_accessor!(static_set $name; $($accessors)*)),
528            },)*
529        ];
530        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
531    };
532
533    ($m:ident, $this:ty; events: [$($events:tt)*] $(, $($rest:tt)*)?) => {
534        $m.events = $crate::__ferro_markup_events!($this; [] $($events)*);
535        $crate::__ferro_markup_items!($m, $this; $($($rest)*)?);
536    };
537}
538
539/// `[Name(A, B) => callable, try Name() => callable, ..]` as a constant slice
540/// of `MarkupEvent`.
541#[doc(hidden)]
542#[macro_export]
543macro_rules! __ferro_markup_events {
544    ($this:ty; [$($done:expr,)*]) => {
545        &[$($done),*]
546    };
547    ($this:ty; [$($done:expr,)*] $name:ident ($($argument:ty),* $(,)?) => $add:expr $(, $($rest:tt)*)?) => {
548        $crate::__ferro_markup_events!($this; [$($done,)* $crate::metadata::MarkupEvent {
549            name: ::std::stringify!($name),
550            arguments: &[$(|| $crate::data::core::ValueType::of::<$argument>()),*],
551            add: |arguments| {
552                let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 2)?;
553                let this = arguments.next::<$this>()?;
554                let handler = arguments.next::<$crate::metadata::MarkupDelegate>()?;
555                let _ = ($add)(&this, handler);
556                ::std::result::Result::Ok(::std::option::Option::None)
557            },
558        },] $($($rest)*)?)
559    };
560    ($this:ty; [$($done:expr,)*] try $name:ident ($($argument:ty),* $(,)?) => $add:expr $(, $($rest:tt)*)?) => {
561        $crate::__ferro_markup_events!($this; [$($done,)* $crate::metadata::MarkupEvent {
562            name: ::std::stringify!($name),
563            arguments: &[$(|| $crate::data::core::ValueType::of::<$argument>()),*],
564            add: |arguments| {
565                let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 2)?;
566                let this = arguments.next::<$this>()?;
567                let handler = arguments.next::<$crate::metadata::MarkupDelegate>()?;
568                let _ = $crate::metadata::markup_result(($add)(&this, handler))?;
569                ::std::result::Result::Ok(::std::option::Option::None)
570            },
571        },] $($($rest)*)?)
572    };
573}
574
575/// `[(A, B) => callable, try (A) => callable, (name: A [Attribute(..)], b: B) => callable, ..]`
576/// as a constant slice of `MarkupConstructor`.
577#[doc(hidden)]
578#[macro_export]
579macro_rules! __ferro_markup_constructors {
580    ([$($pool:ident)*] [$($done:expr,)*]) => {
581        &[$($done),*]
582    };
583    ([$index:ident $($pool:ident)*] [$($done:expr,)*] ($($parameters:tt)*) => $new:expr $(, $($rest:tt)*)?) => {
584        $crate::__ferro_markup_constructors!([$($pool)*] [$($done,)*
585            $crate::__ferro_markup_constructor!($index [] ($new) [] [] $($parameters)*),
586        ] $($($rest)*)?)
587    };
588    ([$index:ident $($pool:ident)*] [$($done:expr,)*] try ($($parameters:tt)*) => $new:expr $(, $($rest:tt)*)?) => {
589        $crate::__ferro_markup_constructors!([$($pool)*] [$($done,)*
590            $crate::__ferro_markup_constructor!($index [try] ($new) [] [] $($parameters)*),
591        ] $($($rest)*)?)
592    };
593}
594
595/// One `MarkupConstructor`: `[try]? (callable) [types] [parameter info] parameters..`.
596/// A parameter is `Type` (positional form) or `name: Type` with an optional
597/// attribute list; a constructor whose parameters are all positional has no
598/// parameter info.
599#[doc(hidden)]
600#[macro_export]
601macro_rules! __ferro_markup_constructor {
602    ($index:ident $try_:tt ($new:expr) [$($parameter:ty,)*] [$($info:expr,)*]) => {
603        $crate::metadata::MarkupConstructor {
604            parameters: &[$(|| $crate::data::core::ValueType::of::<$parameter>()),*],
605            parameter_info: &[$($info),*],
606            invoke: |arguments| {
607                #[allow(unused_mut, unused_variables)]
608                let mut arguments = $crate::metadata::MarkupArguments::new(
609                    arguments,
610                    <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
611                )?;
612                $crate::__ferro_markup_constructor_result!(
613                    $try_ ($new)($(arguments.next::<$parameter>()?),*)
614                )
615            },
616            emit: $crate::__ferro_compiler_metadata!(@value ::std::option::Option::Some($crate::metadata::MarkupEmit {
617                function: ::std::concat!("__markup_new", ::std::stringify!($index)),
618                fallible: $crate::__ferro_markup_is_try!($try_),
619            })),
620        }
621    };
622    ($index:ident $try_:tt $new:tt [$($parameter:ty,)*] [$($info:expr,)*]
623        $name:ident : $type_:ty [$($attributes:tt)*] $(, $($rest:tt)*)?
624    ) => {
625        $crate::__ferro_markup_constructor!($index $try_ $new [$($parameter,)* $type_,] [$($info,)*
626            $crate::metadata::MarkupParameter {
627                name: ::std::option::Option::Some(::std::stringify!($name)),
628                attributes: $crate::__ferro_markup_attributes!([] $($attributes)*),
629            },
630        ] $($($rest)*)?)
631    };
632    ($index:ident $try_:tt $new:tt [$($parameter:ty,)*] [$($info:expr,)*]
633        $name:ident : $type_:ty $(, $($rest:tt)*)?
634    ) => {
635        $crate::__ferro_markup_constructor!($index $try_ $new [$($parameter,)* $type_,] [$($info,)*
636            $crate::metadata::MarkupParameter {
637                name: ::std::option::Option::Some(::std::stringify!($name)),
638                attributes: &[],
639            },
640        ] $($($rest)*)?)
641    };
642    // The positional form: all parameters are types.
643    ($index:ident $try_:tt $new:tt [] [] $($type_:ty),+ $(,)?) => {
644        $crate::__ferro_markup_constructor!($index $try_ $new [$($type_,)+] [])
645    };
646}
647
648#[doc(hidden)]
649#[macro_export]
650macro_rules! __ferro_markup_constructor_result {
651    ([] $($call:tt)*) => {
652        ::std::result::Result::Ok($crate::metadata::into_markup_value($($call)*))
653    };
654    ([try] $($call:tt)*) => {
655        ::std::result::Result::Ok($crate::metadata::into_markup_value(
656            $crate::metadata::markup_result($($call)*)?,
657        ))
658    };
659}
660
661#[doc(hidden)]
662#[macro_export]
663macro_rules! __ferro_markup_enum_variant {
664    ($type_:ident, $member:ident) => {
665        $type_::$member
666    };
667    ($type_:ident, $member:ident, $variant:ident) => {
668        $type_::$variant
669    };
670}
671
672/// The identifier of the Rust variant of an enumeration member, as text.
673#[doc(hidden)]
674#[macro_export]
675macro_rules! __ferro_markup_enum_variant_name {
676    ($member:ident) => {
677        ::std::stringify!($member)
678    };
679    ($member:ident, $variant:ident) => {
680        ::std::stringify!($variant)
681    };
682}
683
684#[doc(hidden)]
685#[macro_export]
686macro_rules! __ferro_markup_unit {
687    ($type_:ty) => {
688        ()
689    };
690}
691
692#[doc(hidden)]
693#[macro_export]
694macro_rules! __ferro_markup_getter {
695    ($this:ty, $type_:ty;) => {
696        ::std::option::Option::None
697    };
698    ($this:ty, $type_:ty; get: $get:expr $(, $($rest:tt)*)?) => {
699        ::std::option::Option::Some(|arguments| {
700            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 1)?;
701            let this = arguments.next::<$this>()?;
702            ::std::result::Result::Ok($crate::metadata::into_markup_value::<$type_>(($get)(&this)))
703        })
704    };
705    ($this:ty, $type_:ty; try_get: $get:expr $(, $($rest:tt)*)?) => {
706        ::std::option::Option::Some(|arguments| {
707            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 1)?;
708            let this = arguments.next::<$this>()?;
709            ::std::result::Result::Ok($crate::metadata::into_markup_value::<$type_>(
710                $crate::metadata::markup_result(($get)(&this))?,
711            ))
712        })
713    };
714    ($this:ty, $type_:ty; set: $set:expr $(, $($rest:tt)*)?) => {
715        $crate::__ferro_markup_getter!($this, $type_; $($($rest)*)?)
716    };
717    ($this:ty, $type_:ty; try_set: $set:expr $(, $($rest:tt)*)?) => {
718        $crate::__ferro_markup_getter!($this, $type_; $($($rest)*)?)
719    };
720}
721
722#[doc(hidden)]
723#[macro_export]
724macro_rules! __ferro_markup_setter {
725    ($this:ty, $type_:ty;) => {
726        ::std::option::Option::None
727    };
728    ($this:ty, $type_:ty; set: $set:expr $(, $($rest:tt)*)?) => {
729        ::std::option::Option::Some(|arguments| {
730            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 2)?;
731            let this = arguments.next::<$this>()?;
732            let value = arguments.next::<$type_>()?;
733            let _ = ($set)(&this, value);
734            ::std::result::Result::Ok(::std::option::Option::None)
735        })
736    };
737    ($this:ty, $type_:ty; try_set: $set:expr $(, $($rest:tt)*)?) => {
738        ::std::option::Option::Some(|arguments| {
739            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 2)?;
740            let this = arguments.next::<$this>()?;
741            let value = arguments.next::<$type_>()?;
742            let _ = $crate::metadata::markup_result(($set)(&this, value))?;
743            ::std::result::Result::Ok(::std::option::Option::None)
744        })
745    };
746    ($this:ty, $type_:ty; get: $get:expr $(, $($rest:tt)*)?) => {
747        $crate::__ferro_markup_setter!($this, $type_; $($($rest)*)?)
748    };
749    ($this:ty, $type_:ty; try_get: $get:expr $(, $($rest:tt)*)?) => {
750        $crate::__ferro_markup_setter!($this, $type_; $($($rest)*)?)
751    };
752}
753
754/// The typed path hook of a property (`MarkupProperty::typed_path_element`)
755/// from its accessors: `this, type, name; [getter] [setter] accessors..`.
756/// See `metadata::typed_path`.
757#[doc(hidden)]
758#[macro_export]
759macro_rules! __ferro_markup_typed_path {
760    ($this:ty, $type_:ty, $name:expr; [$($get:tt)*] [$($set:tt)*]) => {
761        ::std::option::Option::Some(|builder, accepts_null| {
762            #[allow(unused_imports)]
763            use $crate::metadata::typed_path::{
764                TypedPathFallback as _, TypedPathNotifying as _, TypedPathShared as _,
765            };
766            let get: ::std::option::Option<$crate::metadata::typed_path::TypedPathGetter<$this, $type_>> =
767                $crate::__ferro_markup_typed_path!(@getter $this, $type_; $($get)*);
768            let set: ::std::option::Option<$crate::metadata::typed_path::TypedPathSetter<$this, $type_>> =
769                $crate::__ferro_markup_typed_path!(@setter $this, $type_; $($set)*);
770            // The most specific form that applies: a notifying shared type, a shared
771            // type, anything else (see `metadata::typed_path`).
772            (&&$crate::metadata::typed_path::TypedPathProbe::<$this, $type_>::new())
773                .typed_path_element(builder, accepts_null, $name, get, set)
774        })
775    };
776    ($this:ty, $type_:ty, $name:expr; [$($get:tt)*] $set:tt get: $new:expr $(, $($rest:tt)*)?) => {
777        $crate::__ferro_markup_typed_path!($this, $type_, $name; [get $new] $set $($($rest)*)?)
778    };
779    ($this:ty, $type_:ty, $name:expr; [$($get:tt)*] $set:tt try_get: $new:expr $(, $($rest:tt)*)?) => {
780        $crate::__ferro_markup_typed_path!($this, $type_, $name; [try_get $new] $set $($($rest)*)?)
781    };
782    ($this:ty, $type_:ty, $name:expr; $get:tt [$($set:tt)*] set: $new:expr $(, $($rest:tt)*)?) => {
783        $crate::__ferro_markup_typed_path!($this, $type_, $name; $get [set $new] $($($rest)*)?)
784    };
785    // A setter that can fail has no typed form: its failure is reported by
786    // the untyped accessors.
787    ($this:ty, $type_:ty, $name:expr; $get:tt $set:tt try_set: $new:expr $(, $($rest:tt)*)?) => {
788        ::std::option::Option::None
789    };
790
791    (@getter $this:ty, $type_:ty;) => {
792        ::std::option::Option::None
793    };
794    (@getter $this:ty, $type_:ty; get $get:expr) => {
795        ::std::option::Option::Some(::std::rc::Rc::new(
796            |this: &$this| -> ::std::result::Result<$type_, $crate::data::BindingError> {
797                ::std::result::Result::Ok(($get)(this))
798            },
799        ))
800    };
801    (@getter $this:ty, $type_:ty; try_get $get:expr) => {
802        ::std::option::Option::Some(::std::rc::Rc::new(
803            |this: &$this| -> ::std::result::Result<$type_, $crate::data::BindingError> {
804                ($get)(this).map_err(|error| $crate::data::BindingError::message(::std::string::ToString::to_string(&error)))
805            },
806        ))
807    };
808    (@setter $this:ty, $type_:ty;) => {
809        ::std::option::Option::None
810    };
811    (@setter $this:ty, $type_:ty; set $set:expr) => {
812        ::std::option::Option::Some(::std::rc::Rc::new(|this: &$this, value: $type_| {
813            let _ = ($set)(this, value);
814        }))
815    };
816}
817
818/// The getter of a static property: `() -> value`.
819#[doc(hidden)]
820#[macro_export]
821macro_rules! __ferro_markup_static_getter {
822    ($type_:ty;) => {
823        ::std::option::Option::None
824    };
825    ($type_:ty; get: $get:expr $(, $($rest:tt)*)?) => {
826        ::std::option::Option::Some(|arguments| {
827            $crate::metadata::MarkupArguments::new(arguments, 0)?;
828            ::std::result::Result::Ok($crate::metadata::into_markup_value::<$type_>(($get)()))
829        })
830    };
831    ($type_:ty; try_get: $get:expr $(, $($rest:tt)*)?) => {
832        ::std::option::Option::Some(|arguments| {
833            $crate::metadata::MarkupArguments::new(arguments, 0)?;
834            ::std::result::Result::Ok($crate::metadata::into_markup_value::<$type_>(
835                $crate::metadata::markup_result(($get)())?,
836            ))
837        })
838    };
839    ($type_:ty; set: $set:expr $(, $($rest:tt)*)?) => {
840        $crate::__ferro_markup_static_getter!($type_; $($($rest)*)?)
841    };
842    ($type_:ty; try_set: $set:expr $(, $($rest:tt)*)?) => {
843        $crate::__ferro_markup_static_getter!($type_; $($($rest)*)?)
844    };
845}
846
847/// The setter of a static property: `(value)`.
848#[doc(hidden)]
849#[macro_export]
850macro_rules! __ferro_markup_static_setter {
851    ($type_:ty;) => {
852        ::std::option::Option::None
853    };
854    ($type_:ty; set: $set:expr $(, $($rest:tt)*)?) => {
855        ::std::option::Option::Some(|arguments| {
856            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 1)?;
857            let _ = ($set)(arguments.next::<$type_>()?);
858            ::std::result::Result::Ok(::std::option::Option::None)
859        })
860    };
861    ($type_:ty; try_set: $set:expr $(, $($rest:tt)*)?) => {
862        ::std::option::Option::Some(|arguments| {
863            let mut arguments = $crate::metadata::MarkupArguments::new(arguments, 1)?;
864            let _ = $crate::metadata::markup_result(($set)(arguments.next::<$type_>()?))?;
865            ::std::result::Result::Ok(::std::option::Option::None)
866        })
867    };
868    ($type_:ty; get: $get:expr $(, $($rest:tt)*)?) => {
869        $crate::__ferro_markup_static_setter!($type_; $($($rest)*)?)
870    };
871    ($type_:ty; try_get: $get:expr $(, $($rest:tt)*)?) => {
872        $crate::__ferro_markup_static_setter!($type_; $($($rest)*)?)
873    };
874}
875
876/// `[fn Name(A, B) -> R => callable, static fn Name(A) => callable [Attribute(..)], ..]`
877/// as a constant slice of `MarkupMethod`.
878///
879/// Each entry is recognised in one step (the list is as deep as it has
880/// entries) and handed to `__ferro_markup_method!`. A callable followed by an
881/// attribute list is a plain path (`Type::method`) or a parenthesised
882/// expression: an expression cannot be followed by `[` in a declaration
883/// macro.
884#[doc(hidden)]
885#[macro_export]
886macro_rules! __ferro_markup_methods {
887    ([$($pool:ident)*] $this:ty; [$($done:expr,)*]) => {
888        &[$($done),*]
889    };
890
891    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
892        static try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
893    ) => {
894        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
895            $index $this; [static] [try] $name ($($parameter),*) ($($return_)?) ($call $(:: $segment)*) [$($attributes)*]
896        ),] $($($rest)*)?)
897    };
898
899    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
900        static try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
901    ) => {
902        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
903            $index $this; [static] [try] $name ($($parameter),*) ($($return_)?) (($($call)*)) [$($attributes)*]
904        ),] $($($rest)*)?)
905    };
906
907    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
908        static try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
909    ) => {
910        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
911            $index $this; [static] [try] $name ($($parameter),*) ($($return_)?) ($call) []
912        ),] $($($rest)*)?)
913    };
914
915    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
916        static fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
917    ) => {
918        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
919            $index $this; [static] [] $name ($($parameter),*) ($($return_)?) ($call $(:: $segment)*) [$($attributes)*]
920        ),] $($($rest)*)?)
921    };
922
923    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
924        static fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
925    ) => {
926        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
927            $index $this; [static] [] $name ($($parameter),*) ($($return_)?) (($($call)*)) [$($attributes)*]
928        ),] $($($rest)*)?)
929    };
930
931    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
932        static fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
933    ) => {
934        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
935            $index $this; [static] [] $name ($($parameter),*) ($($return_)?) ($call) []
936        ),] $($($rest)*)?)
937    };
938
939    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
940        try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
941    ) => {
942        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
943            $index $this; [] [try] $name ($($parameter),*) ($($return_)?) ($call $(:: $segment)*) [$($attributes)*]
944        ),] $($($rest)*)?)
945    };
946
947    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
948        try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
949    ) => {
950        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
951            $index $this; [] [try] $name ($($parameter),*) ($($return_)?) (($($call)*)) [$($attributes)*]
952        ),] $($($rest)*)?)
953    };
954
955    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
956        try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
957    ) => {
958        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
959            $index $this; [] [try] $name ($($parameter),*) ($($return_)?) ($call) []
960        ),] $($($rest)*)?)
961    };
962
963    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
964        fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
965    ) => {
966        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
967            $index $this; [] [] $name ($($parameter),*) ($($return_)?) ($call $(:: $segment)*) [$($attributes)*]
968        ),] $($($rest)*)?)
969    };
970
971    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
972        fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
973    ) => {
974        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
975            $index $this; [] [] $name ($($parameter),*) ($($return_)?) (($($call)*)) [$($attributes)*]
976        ),] $($($rest)*)?)
977    };
978
979    ([$index:ident $($pool:ident)*] $this:ty; [$($done:expr,)*]
980        fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
981    ) => {
982        $crate::__ferro_markup_methods!([$($pool)*] $this; [$($done,)* $crate::__ferro_markup_method!(
983            $index $this; [] [] $name ($($parameter),*) ($($return_)?) ($call) []
984        ),] $($($rest)*)?)
985    };
986}
987
988/// The typed functions of `methods: [..]` (see `MarkupEmit`), in declaration order: the
989/// same order and pool of indices as [`__ferro_markup_methods!`].
990#[doc(hidden)]
991#[macro_export]
992macro_rules! __ferro_markup_method_fns {
993    ([$($pool:ident)*] $this:ty;) => {};
994
995    ([$index:ident $($pool:ident)*] $this:ty;
996        static try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
997    ) => {
998        $crate::__ferro_markup_method_fn!(
999            $index [static] [try] $this; $name ($($return_)?) ($call $(:: $segment)*) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1000        );
1001        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1002    };
1003
1004    ([$index:ident $($pool:ident)*] $this:ty;
1005        static try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
1006    ) => {
1007        $crate::__ferro_markup_method_fn!(
1008            $index [static] [try] $this; $name ($($return_)?) (($($call)*)) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1009        );
1010        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1011    };
1012
1013    ([$index:ident $($pool:ident)*] $this:ty;
1014        static try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
1015    ) => {
1016        $crate::__ferro_markup_method_fn!(
1017            $index [static] [try] $this; $name ($($return_)?) ($call) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1018        );
1019        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1020    };
1021
1022    ([$index:ident $($pool:ident)*] $this:ty;
1023        static fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
1024    ) => {
1025        $crate::__ferro_markup_method_fn!(
1026            $index [static] [] $this; $name ($($return_)?) ($call $(:: $segment)*) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1027        );
1028        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1029    };
1030
1031    ([$index:ident $($pool:ident)*] $this:ty;
1032        static fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
1033    ) => {
1034        $crate::__ferro_markup_method_fn!(
1035            $index [static] [] $this; $name ($($return_)?) (($($call)*)) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1036        );
1037        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1038    };
1039
1040    ([$index:ident $($pool:ident)*] $this:ty;
1041        static fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
1042    ) => {
1043        $crate::__ferro_markup_method_fn!(
1044            $index [static] [] $this; $name ($($return_)?) ($call) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1045        );
1046        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1047    };
1048
1049    ([$index:ident $($pool:ident)*] $this:ty;
1050        try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
1051    ) => {
1052        $crate::__ferro_markup_method_fn!(
1053            $index [] [try] $this; $name ($($return_)?) ($call $(:: $segment)*) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1054        );
1055        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1056    };
1057
1058    ([$index:ident $($pool:ident)*] $this:ty;
1059        try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
1060    ) => {
1061        $crate::__ferro_markup_method_fn!(
1062            $index [] [try] $this; $name ($($return_)?) (($($call)*)) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1063        );
1064        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1065    };
1066
1067    ([$index:ident $($pool:ident)*] $this:ty;
1068        try fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
1069    ) => {
1070        $crate::__ferro_markup_method_fn!(
1071            $index [] [try] $this; $name ($($return_)?) ($call) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1072        );
1073        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1074    };
1075
1076    ([$index:ident $($pool:ident)*] $this:ty;
1077        fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:ident $(:: $segment:ident)* [$($attributes:tt)*] $(, $($rest:tt)*)?
1078    ) => {
1079        $crate::__ferro_markup_method_fn!(
1080            $index [] [] $this; $name ($($return_)?) ($call $(:: $segment)*) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1081        );
1082        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1083    };
1084
1085    ([$index:ident $($pool:ident)*] $this:ty;
1086        fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => ($($call:tt)*) [$($attributes:tt)*] $(, $($rest:tt)*)?
1087    ) => {
1088        $crate::__ferro_markup_method_fn!(
1089            $index [] [] $this; $name ($($return_)?) (($($call)*)) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1090        );
1091        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1092    };
1093
1094    ([$index:ident $($pool:ident)*] $this:ty;
1095        fn $name:ident ($($parameter:ty),* $(,)?) $(-> $return_:ty)? => $call:expr  $(, $($rest:tt)*)?
1096    ) => {
1097        $crate::__ferro_markup_method_fn!(
1098            $index [] [] $this; $name ($($return_)?) ($call) [] [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1099        );
1100        $crate::__ferro_markup_method_fns!([$($pool)*] $this; $($($rest)*)?);
1101    };
1102}
1103
1104/// A pool of indices for the members of one declaration that have no
1105/// unique name (overloaded methods): the data of the metadata and the typed
1106/// functions both take the indices from here, in declaration order.
1107#[doc(hidden)]
1108#[macro_export]
1109macro_rules! __ferro_markup_pool {
1110    (methods { $($arguments:tt)* }) => {
1111        $crate::__ferro_markup_methods!([_0 _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] $($arguments)*)
1112    };
1113    (method_fns { $($arguments:tt)* }) => {
1114        $crate::__ferro_markup_method_fns!([_0 _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] $($arguments)*);
1115    };
1116    (constructors { $($arguments:tt)* }) => {
1117        $crate::__ferro_markup_constructors!([_0 _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] $($arguments)*)
1118    };
1119    (constructor_fns { $($arguments:tt)* }) => {
1120        $crate::__ferro_markup_constructor_fns!([_0 _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] $($arguments)*);
1121    };
1122}
1123
1124/// Whether a member is declared with `try`.
1125#[doc(hidden)]
1126#[macro_export]
1127macro_rules! __ferro_markup_is_try {
1128    ([]) => {
1129        false
1130    };
1131    ([try]) => {
1132        true
1133    };
1134}
1135
1136/// The `MarkupEmit` of an accessor of a property: `get` / `set` /
1137/// `static_get` / `static_set`, the name, the accessors.
1138#[doc(hidden)]
1139#[macro_export]
1140macro_rules! __ferro_markup_emit_accessor {
1141    ($which:ident $name:ident;) => {
1142        ::std::option::Option::None
1143    };
1144    (get $name:ident; get: $accessor:expr $(, $($rest:tt)*)?) => {
1145        $crate::__ferro_markup_emit_accessor!(@emit "__markup_get_", $name, false)
1146    };
1147    (get $name:ident; try_get: $accessor:expr $(, $($rest:tt)*)?) => {
1148        $crate::__ferro_markup_emit_accessor!(@emit "__markup_get_", $name, true)
1149    };
1150    (set $name:ident; set: $accessor:expr $(, $($rest:tt)*)?) => {
1151        $crate::__ferro_markup_emit_accessor!(@emit "__markup_set_", $name, false)
1152    };
1153    (set $name:ident; try_set: $accessor:expr $(, $($rest:tt)*)?) => {
1154        $crate::__ferro_markup_emit_accessor!(@emit "__markup_set_", $name, true)
1155    };
1156    (static_get $name:ident; get: $accessor:expr $(, $($rest:tt)*)?) => {
1157        $crate::__ferro_markup_emit_accessor!(@emit "__markup_static_get_", $name, false)
1158    };
1159    (static_get $name:ident; try_get: $accessor:expr $(, $($rest:tt)*)?) => {
1160        $crate::__ferro_markup_emit_accessor!(@emit "__markup_static_get_", $name, true)
1161    };
1162    (static_set $name:ident; set: $accessor:expr $(, $($rest:tt)*)?) => {
1163        $crate::__ferro_markup_emit_accessor!(@emit "__markup_static_set_", $name, false)
1164    };
1165    (static_set $name:ident; try_set: $accessor:expr $(, $($rest:tt)*)?) => {
1166        $crate::__ferro_markup_emit_accessor!(@emit "__markup_static_set_", $name, true)
1167    };
1168    (@emit $prefix:literal, $name:ident, $fallible:literal) => {
1169        ::std::option::Option::Some($crate::metadata::MarkupEmit {
1170            function: ::std::concat!($prefix, ::std::stringify!($name)),
1171            fallible: $fallible,
1172        })
1173    };
1174    ($which:ident $name:ident; $other:ident : $accessor:expr $(, $($rest:tt)*)?) => {
1175        $crate::__ferro_markup_emit_accessor!($which $name; $($($rest)*)?)
1176    };
1177}
1178
1179/// The typed functions of a declaration (see `MarkupEmit`), as associated
1180/// functions of the declared type: written into an `impl` block of the type
1181/// by [`ferro_markup_type!`](crate::ferro_markup_type) and
1182/// [`ferro_class_info!`](crate::ferro_class_info). `this, value; parts..`:
1183/// the instance type, the type of a value of the type (what `Parse`
1184/// returns: the type itself, `Rc<dyn Trait>` for a contract) and the parts
1185/// of the declaration body, as `__ferro_markup_items!` reads them.
1186#[doc(hidden)]
1187#[macro_export]
1188macro_rules! __ferro_markup_fns {
1189    ($this:ty, $value:ty;) => {};
1190
1191    ($this:ty, $value:ty; properties: [
1192        $($name:ident : $type_:ty { $($accessors:tt)* } $([$($attributes:tt)*])?),* $(,)?
1193    ] $(, $($rest:tt)*)?) => {
1194        $($crate::__ferro_markup_property_fns!($this, $type_, $name; $($accessors)*);)*
1195        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1196    };
1197
1198    ($this:ty, $value:ty; static_properties: [
1199        $($name:ident : $type_:ty { $($accessors:tt)* } $([$($attributes:tt)*])?),* $(,)?
1200    ] $(, $($rest:tt)*)?) => {
1201        $($crate::__ferro_markup_static_property_fns!($type_, $name; $($accessors)*);)*
1202        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1203    };
1204
1205    ($this:ty, $value:ty; methods: [$($methods:tt)*] $(, $($rest:tt)*)?) => {
1206        $crate::__ferro_markup_pool!(method_fns { $this; $($methods)* });
1207        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1208    };
1209
1210    // The other parts declare no typed function.
1211    ($this:ty, $value:ty; namespace: $namespace:literal $(, $($rest:tt)*)?) => {
1212        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1213    };
1214    ($this:ty, $value:ty; handles: [$($handle:ty),* $(,)?] $(, $($rest:tt)*)?) => {
1215        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1216    };
1217    ($this:ty, $value:ty; base: $base:ty $(, $($rest:tt)*)?) => {
1218        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1219    };
1220    ($this:ty, $value:ty; interfaces: [$($interface:ty),* $(,)?] $(, $($rest:tt)*)?) => {
1221        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1222    };
1223    ($this:ty, $value:ty; generic: $definition:literal [$($argument:ty),* $(,)?] $(, $($rest:tt)*)?) => {
1224        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1225    };
1226    ($this:ty, $value:ty; content: $content:ident $(, $($rest:tt)*)?) => {
1227        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1228    };
1229    ($this:ty, $value:ty; attributes: [$($attributes:tt)*] $(, $($rest:tt)*)?) => {
1230        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1231    };
1232    ($this:ty, $value:ty; constructors: [$($constructors:tt)*] $(, $($rest:tt)*)?) => {
1233        $crate::__ferro_markup_pool!(constructor_fns { $value; $($constructors)* });
1234        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1235    };
1236    ($this:ty, $value:ty; parse: $parse:expr $(, $($rest:tt)*)?) => {
1237        /// The typed function of the `Parse(string)` of the type (see `MarkupEmit`).
1238        #[doc(hidden)]
1239        #[allow(private_interfaces, clippy::all)]
1240        #[inline]
1241        pub fn __markup_parse(text: ::std::string::String) -> ::std::result::Result<$value, $crate::metadata::MarkupInvokeError> {
1242            $crate::metadata::markup_result(($parse)(text.as_str()))
1243        }
1244        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1245    };
1246    ($this:ty, $value:ty; indexers: [$($indexers:tt)*] $(, $($rest:tt)*)?) => {
1247        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1248    };
1249    ($this:ty, $value:ty; property_attributes: [$($attributes:tt)*] $(, $($rest:tt)*)?) => {
1250        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1251    };
1252    ($this:ty, $value:ty; notify_property_changed: $object:ty $(, $($rest:tt)*)?) => {
1253        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1254    };
1255    ($this:ty, $value:ty; type_info: $type_info:ty $(, $($rest:tt)*)?) => {
1256        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1257    };
1258    ($this:ty, $value:ty; fields: [$($name:ident : $type_:ty => $get:expr),* $(,)?] $(, $($rest:tt)*)?) => {
1259        $crate::__paste! {
1260            $(
1261                /// The typed function of a static field (see `MarkupEmit`).
1262                #[doc(hidden)]
1263                #[allow(non_snake_case, private_interfaces, clippy::all)]
1264                #[inline]
1265                pub fn [<__markup_field_ $name>]() -> $type_ {
1266                    ($get)()
1267                }
1268            )*
1269        }
1270        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1271    };
1272    ($this:ty, $value:ty; events: [$($events:tt)*] $(, $($rest:tt)*)?) => {
1273        $crate::__ferro_markup_fns!($this, $value; $($($rest)*)?);
1274    };
1275}
1276
1277/// The typed accessor functions of an instance property.
1278#[doc(hidden)]
1279#[macro_export]
1280macro_rules! __ferro_markup_property_fns {
1281    ($this:ty, $type_:ty, $name:ident;) => {};
1282    ($this:ty, $type_:ty, $name:ident; get: $get:expr $(, $($rest:tt)*)?) => {
1283        $crate::__paste! {
1284            #[doc(hidden)]
1285            #[allow(non_snake_case, private_interfaces, clippy::all)]
1286            #[inline]
1287            pub fn [<__markup_get_ $name>](this: &$this) -> $type_ {
1288                ($get)(this)
1289            }
1290        }
1291        $crate::__ferro_markup_property_fns!($this, $type_, $name; $($($rest)*)?);
1292    };
1293    ($this:ty, $type_:ty, $name:ident; try_get: $get:expr $(, $($rest:tt)*)?) => {
1294        $crate::__paste! {
1295            #[doc(hidden)]
1296            #[allow(non_snake_case, private_interfaces, clippy::all)]
1297            #[inline]
1298            pub fn [<__markup_get_ $name>](
1299                this: &$this,
1300            ) -> ::std::result::Result<$type_, $crate::metadata::MarkupInvokeError> {
1301                $crate::metadata::markup_result(($get)(this))
1302            }
1303        }
1304        $crate::__ferro_markup_property_fns!($this, $type_, $name; $($($rest)*)?);
1305    };
1306    ($this:ty, $type_:ty, $name:ident; set: $set:expr $(, $($rest:tt)*)?) => {
1307        $crate::__paste! {
1308            #[doc(hidden)]
1309            #[allow(non_snake_case, private_interfaces, clippy::all)]
1310            #[inline]
1311            pub fn [<__markup_set_ $name>](this: &$this, value: $type_) {
1312                let _ = ($set)(this, value);
1313            }
1314        }
1315        $crate::__ferro_markup_property_fns!($this, $type_, $name; $($($rest)*)?);
1316    };
1317    ($this:ty, $type_:ty, $name:ident; try_set: $set:expr $(, $($rest:tt)*)?) => {
1318        $crate::__paste! {
1319            #[doc(hidden)]
1320            #[allow(non_snake_case, private_interfaces, clippy::all)]
1321            #[inline]
1322            pub fn [<__markup_set_ $name>](
1323                this: &$this,
1324                value: $type_,
1325            ) -> ::std::result::Result<(), $crate::metadata::MarkupInvokeError> {
1326                $crate::metadata::markup_result(($set)(this, value)).map(|_| ())
1327            }
1328        }
1329        $crate::__ferro_markup_property_fns!($this, $type_, $name; $($($rest)*)?);
1330    };
1331}
1332
1333/// The typed accessor functions of a static property.
1334#[doc(hidden)]
1335#[macro_export]
1336macro_rules! __ferro_markup_static_property_fns {
1337    ($type_:ty, $name:ident;) => {};
1338    ($type_:ty, $name:ident; get: $get:expr $(, $($rest:tt)*)?) => {
1339        $crate::__paste! {
1340            #[doc(hidden)]
1341            #[allow(non_snake_case, private_interfaces, clippy::all)]
1342            #[inline]
1343            pub fn [<__markup_static_get_ $name>]() -> $type_ {
1344                ($get)()
1345            }
1346        }
1347        $crate::__ferro_markup_static_property_fns!($type_, $name; $($($rest)*)?);
1348    };
1349    ($type_:ty, $name:ident; try_get: $get:expr $(, $($rest:tt)*)?) => {
1350        $crate::__paste! {
1351            #[doc(hidden)]
1352            #[allow(non_snake_case, private_interfaces, clippy::all)]
1353            #[inline]
1354            pub fn [<__markup_static_get_ $name>]() -> ::std::result::Result<$type_, $crate::metadata::MarkupInvokeError> {
1355                $crate::metadata::markup_result(($get)())
1356            }
1357        }
1358        $crate::__ferro_markup_static_property_fns!($type_, $name; $($($rest)*)?);
1359    };
1360    ($type_:ty, $name:ident; set: $set:expr $(, $($rest:tt)*)?) => {
1361        $crate::__paste! {
1362            #[doc(hidden)]
1363            #[allow(non_snake_case, private_interfaces, clippy::all)]
1364            #[inline]
1365            pub fn [<__markup_static_set_ $name>](value: $type_) {
1366                let _ = ($set)(value);
1367            }
1368        }
1369        $crate::__ferro_markup_static_property_fns!($type_, $name; $($($rest)*)?);
1370    };
1371    ($type_:ty, $name:ident; try_set: $set:expr $(, $($rest:tt)*)?) => {
1372        $crate::__paste! {
1373            #[doc(hidden)]
1374            #[allow(non_snake_case, private_interfaces, clippy::all)]
1375            #[inline]
1376            pub fn [<__markup_static_set_ $name>](
1377                value: $type_,
1378            ) -> ::std::result::Result<(), $crate::metadata::MarkupInvokeError> {
1379                $crate::metadata::markup_result(($set)(value)).map(|_| ())
1380            }
1381        }
1382        $crate::__ferro_markup_static_property_fns!($type_, $name; $($($rest)*)?);
1383    };
1384}
1385
1386/// The typed function of one method: `index [static]? [try]? this; Name
1387/// (return)? (callable) [arguments] [names] (parameters)`: the parameters are
1388/// paired with names from the pool of names, then the function is written.
1389#[doc(hidden)]
1390#[macro_export]
1391macro_rules! __ferro_markup_method_fn {
1392    ($index:ident $static_:tt $try_:tt $this:ty; $name:ident ($($return_:ty)?) ($call:expr)
1393        [$($argument:ident : $parameter:ty,)*] [$($names:ident)*] ()
1394    ) => {
1395        $crate::__ferro_markup_method_fn!(@emit $index $static_ $try_ $this; $name ($($return_)?) ($call)
1396            [$($argument : $parameter,)*]);
1397    };
1398    ($index:ident $static_:tt $try_:tt $this:ty; $name:ident ($($return_:ty)?) ($call:expr)
1399        [$($done:tt)*] [$next:ident $($names:ident)*] ($parameter:ty $(, $rest:ty)*)
1400    ) => {
1401        $crate::__ferro_markup_method_fn!($index $static_ $try_ $this; $name ($($return_)?) ($call)
1402            [$($done)* $next : $parameter,] [$($names)*] ($($rest),*));
1403    };
1404    (@emit $index:ident [] $try_:tt $this:ty; $name:ident ($($return_:ty)?) ($call:expr)
1405        [$($argument:ident : $parameter:ty,)*]
1406    ) => {
1407        $crate::__paste! {
1408            #[doc(hidden)]
1409            #[allow(non_snake_case, private_interfaces, clippy::all)]
1410            #[inline]
1411            pub fn [<__markup_ $name $index>](
1412                this: &$this $(, $argument: $parameter)*
1413            ) -> $crate::__ferro_markup_fn_return!($try_ ($($return_)?)) {
1414                $crate::__ferro_markup_fn_body!($try_ ($($return_)?) ($call)(this $(, $argument)*))
1415            }
1416        }
1417    };
1418    (@emit $index:ident [static] $try_:tt $this:ty; $name:ident ($($return_:ty)?) ($call:expr)
1419        [$($argument:ident : $parameter:ty,)*]
1420    ) => {
1421        $crate::__paste! {
1422            #[doc(hidden)]
1423            #[allow(non_snake_case, private_interfaces, clippy::all)]
1424            #[inline]
1425            pub fn [<__markup_ $name $index>](
1426                $($argument: $parameter),*
1427            ) -> $crate::__ferro_markup_fn_return!($try_ ($($return_)?)) {
1428                $crate::__ferro_markup_fn_body!($try_ ($($return_)?) ($call)($($argument),*))
1429            }
1430        }
1431    };
1432}
1433
1434/// The typed functions of `constructors: [..]` (see `MarkupEmit`), in
1435/// declaration order: the same order and pool of indices as
1436/// [`__ferro_markup_constructors!`]. `value` is the type a constructor returns.
1437#[doc(hidden)]
1438#[macro_export]
1439macro_rules! __ferro_markup_constructor_fns {
1440    ([$($pool:ident)*] $value:ty;) => {};
1441    ([$index:ident $($pool:ident)*] $value:ty; ($($parameters:tt)*) => $new:expr $(, $($rest:tt)*)?) => {
1442        $crate::__ferro_markup_constructor_fn!($index [] $value; ($new) [] $($parameters)*);
1443        $crate::__ferro_markup_constructor_fns!([$($pool)*] $value; $($($rest)*)?);
1444    };
1445    ([$index:ident $($pool:ident)*] $value:ty; try ($($parameters:tt)*) => $new:expr $(, $($rest:tt)*)?) => {
1446        $crate::__ferro_markup_constructor_fn!($index [try] $value; ($new) [] $($parameters)*);
1447        $crate::__ferro_markup_constructor_fns!([$($pool)*] $value; $($($rest)*)?);
1448    };
1449}
1450
1451/// The typed function of one constructor: its parameter types are
1452/// collected from the positional or the named form, then the function is
1453/// written as a static method `new` returning `value`.
1454#[doc(hidden)]
1455#[macro_export]
1456macro_rules! __ferro_markup_constructor_fn {
1457    ($index:ident $try_:tt $value:ty; ($new:expr) [$($parameter:ty,)*]) => {
1458        $crate::__ferro_markup_method_fn!(
1459            $index [static] $try_ $value; new ($value) ($new) []
1460            [a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 a10 a11 a12 a13 a14 a15] ($($parameter),*)
1461        );
1462    };
1463    ($index:ident $try_:tt $value:ty; $new:tt [$($parameter:ty,)*]
1464        $name:ident : $type_:ty [$($attributes:tt)*] $(, $($rest:tt)*)?
1465    ) => {
1466        $crate::__ferro_markup_constructor_fn!($index $try_ $value; $new [$($parameter,)* $type_,] $($($rest)*)?);
1467    };
1468    ($index:ident $try_:tt $value:ty; $new:tt [$($parameter:ty,)*]
1469        $name:ident : $type_:ty $(, $($rest:tt)*)?
1470    ) => {
1471        $crate::__ferro_markup_constructor_fn!($index $try_ $value; $new [$($parameter,)* $type_,] $($($rest)*)?);
1472    };
1473    ($index:ident $try_:tt $value:ty; $new:tt [] $($type_:ty),+ $(,)?) => {
1474        $crate::__ferro_markup_constructor_fn!($index $try_ $value; $new [$($type_,)+]);
1475    };
1476}
1477
1478/// The return type of a typed function: `[try]? (return)?`.
1479#[doc(hidden)]
1480#[macro_export]
1481macro_rules! __ferro_markup_fn_return {
1482    ([] ()) => { () };
1483    ([] ($return_:ty)) => { $return_ };
1484    ([try] ()) => { ::std::result::Result<(), $crate::metadata::MarkupInvokeError> };
1485    ([try] ($return_:ty)) => { ::std::result::Result<$return_, $crate::metadata::MarkupInvokeError> };
1486}
1487
1488/// The body of a typed function: `[try]? (return)? call`.
1489#[doc(hidden)]
1490#[macro_export]
1491macro_rules! __ferro_markup_fn_body {
1492    ([] () $($call:tt)*) => {{
1493        let _ = $($call)*;
1494    }};
1495    ([] ($return_:ty) $($call:tt)*) => {
1496        $($call)*
1497    };
1498    ([try] () $($call:tt)*) => {
1499        $crate::metadata::markup_result($($call)*).map(|_| ())
1500    };
1501    ([try] ($return_:ty) $($call:tt)*) => {
1502        $crate::metadata::markup_result($($call)*)
1503    };
1504}
1505
1506/// One `MarkupMethod`: `this; [static]? [try]? Name (parameters) (return)? (callable) [attributes]`.
1507#[doc(hidden)]
1508#[macro_export]
1509macro_rules! __ferro_markup_method {
1510    ($index:ident $this:ty; [] $try_:tt $name:ident ($($parameter:ty),*) ($($return_:ty)?) ($call:expr) [$($attributes:tt)*]) => {
1511        $crate::metadata::MarkupMethod {
1512            name: ::std::stringify!($name),
1513            is_static: false,
1514            parameters: &[$(|| $crate::data::core::ValueType::of::<$parameter>()),*],
1515            return_type: $crate::__ferro_markup_return_type!($($return_)?),
1516            invoke: |arguments| {
1517                let mut arguments = $crate::metadata::MarkupArguments::new(
1518                    arguments,
1519                    1 + <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
1520                )?;
1521                let this = arguments.next::<$this>()?;
1522                $crate::__ferro_markup_method_result!(
1523                    $try_ ($($return_)?) ($call)(&this $(, arguments.next::<$parameter>()?)*)
1524                )
1525            },
1526            attributes: $crate::__ferro_markup_attributes!([] $($attributes)*),
1527            emit: $crate::__ferro_compiler_metadata!(@value ::std::option::Option::Some($crate::metadata::MarkupEmit {
1528                function: ::std::concat!("__markup_", ::std::stringify!($name), ::std::stringify!($index)),
1529                fallible: $crate::__ferro_markup_is_try!($try_),
1530            })),
1531        }
1532    };
1533    ($index:ident $this:ty; [static] $try_:tt $name:ident ($($parameter:ty),*) ($($return_:ty)?) ($call:expr) [$($attributes:tt)*]) => {
1534        $crate::metadata::MarkupMethod {
1535            name: ::std::stringify!($name),
1536            is_static: true,
1537            parameters: &[$(|| $crate::data::core::ValueType::of::<$parameter>()),*],
1538            return_type: $crate::__ferro_markup_return_type!($($return_)?),
1539            invoke: |arguments| {
1540                #[allow(unused_mut, unused_variables)]
1541                let mut arguments = $crate::metadata::MarkupArguments::new(
1542                    arguments,
1543                    <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
1544                )?;
1545                $crate::__ferro_markup_method_result!(
1546                    $try_ ($($return_)?) ($call)($(arguments.next::<$parameter>()?),*)
1547                )
1548            },
1549            attributes: $crate::__ferro_markup_attributes!([] $($attributes)*),
1550            emit: $crate::__ferro_compiler_metadata!(@value ::std::option::Option::Some($crate::metadata::MarkupEmit {
1551                function: ::std::concat!("__markup_", ::std::stringify!($name), ::std::stringify!($index)),
1552                fallible: $crate::__ferro_markup_is_try!($try_),
1553            })),
1554        }
1555    };
1556}
1557
1558#[doc(hidden)]
1559#[macro_export]
1560macro_rules! __ferro_markup_return_type {
1561    () => {
1562        ::std::option::Option::None
1563    };
1564    ($return_:ty) => {
1565        ::std::option::Option::Some(|| $crate::data::core::ValueType::of::<$return_>())
1566    };
1567}
1568
1569/// The result of an invoker from the value of the call: `[try]? (return)? call`.
1570#[doc(hidden)]
1571#[macro_export]
1572macro_rules! __ferro_markup_method_result {
1573    ([] () $($call:tt)*) => {{
1574        let _ = $($call)*;
1575        ::std::result::Result::Ok(::std::option::Option::None)
1576    }};
1577    ([] ($return_:ty) $($call:tt)*) => {
1578        ::std::result::Result::Ok($crate::metadata::into_markup_value::<$return_>($($call)*))
1579    };
1580    ([try] () $($call:tt)*) => {{
1581        let _ = $crate::metadata::markup_result($($call)*)?;
1582        ::std::result::Result::Ok(::std::option::Option::None)
1583    }};
1584    ([try] ($return_:ty) $($call:tt)*) => {
1585        ::std::result::Result::Ok($crate::metadata::into_markup_value::<$return_>(
1586            $crate::metadata::markup_result($($call)*)?,
1587        ))
1588    };
1589}
1590
1591/// `[(A, B) -> T { get: callable, set: callable } [Attribute(..)], ..]` as a
1592/// constant slice of `MarkupIndexer`.
1593#[doc(hidden)]
1594#[macro_export]
1595macro_rules! __ferro_markup_indexers {
1596    ($this:ty; [$($done:expr,)*]) => {
1597        &[$($done),*]
1598    };
1599    ($this:ty; [$($done:expr,)*]
1600        ($($parameter:ty),* $(,)?) -> $type_:ty { $($accessors:tt)* } $([$($attributes:tt)*])? $(, $($rest:tt)*)?
1601    ) => {
1602        $crate::__ferro_markup_indexers!($this; [$($done,)* $crate::metadata::MarkupIndexer {
1603            parameters: &[$(|| $crate::data::core::ValueType::of::<$parameter>()),*],
1604            type_: || $crate::data::core::ValueType::of::<$type_>(),
1605            get: $crate::__ferro_markup_indexer_getter!($this, ($($parameter),*), $type_; $($accessors)*),
1606            set: $crate::__ferro_markup_indexer_setter!($this, ($($parameter),*), $type_; $($accessors)*),
1607            attributes: $crate::__ferro_markup_attributes!([] $($($attributes)*)?),
1608        },] $($($rest)*)?)
1609    };
1610}
1611
1612#[doc(hidden)]
1613#[macro_export]
1614macro_rules! __ferro_markup_indexer_getter {
1615    ($this:ty, ($($parameter:ty),*), $type_:ty;) => {
1616        ::std::option::Option::None
1617    };
1618    ($this:ty, ($($parameter:ty),*), $type_:ty; get: $get:expr $(, $($rest:tt)*)?) => {
1619        ::std::option::Option::Some(|arguments| {
1620            let mut arguments = $crate::metadata::MarkupArguments::new(
1621                arguments,
1622                1 + <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
1623            )?;
1624            let this = arguments.next::<$this>()?;
1625            ::std::result::Result::Ok($crate::metadata::into_markup_value::<$type_>(
1626                ($get)(&this $(, arguments.next::<$parameter>()?)*),
1627            ))
1628        })
1629    };
1630    ($this:ty, ($($parameter:ty),*), $type_:ty; try_get: $get:expr $(, $($rest:tt)*)?) => {
1631        ::std::option::Option::Some(|arguments| {
1632            let mut arguments = $crate::metadata::MarkupArguments::new(
1633                arguments,
1634                1 + <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
1635            )?;
1636            let this = arguments.next::<$this>()?;
1637            ::std::result::Result::Ok($crate::metadata::into_markup_value::<$type_>(
1638                $crate::metadata::markup_result(($get)(&this $(, arguments.next::<$parameter>()?)*))?,
1639            ))
1640        })
1641    };
1642    ($this:ty, ($($parameter:ty),*), $type_:ty; set: $set:expr $(, $($rest:tt)*)?) => {
1643        $crate::__ferro_markup_indexer_getter!($this, ($($parameter),*), $type_; $($($rest)*)?)
1644    };
1645    ($this:ty, ($($parameter:ty),*), $type_:ty; try_set: $set:expr $(, $($rest:tt)*)?) => {
1646        $crate::__ferro_markup_indexer_getter!($this, ($($parameter),*), $type_; $($($rest)*)?)
1647    };
1648}
1649
1650#[doc(hidden)]
1651#[macro_export]
1652macro_rules! __ferro_markup_indexer_setter {
1653    ($this:ty, ($($parameter:ty),*), $type_:ty;) => {
1654        ::std::option::Option::None
1655    };
1656    ($this:ty, ($($parameter:ty),*), $type_:ty; set: $set:expr $(, $($rest:tt)*)?) => {
1657        ::std::option::Option::Some(|arguments| {
1658            let mut arguments = $crate::metadata::MarkupArguments::new(
1659                arguments,
1660                2 + <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
1661            )?;
1662            let this = arguments.next::<$this>()?;
1663            let _ = ($set)(&this $(, arguments.next::<$parameter>()?)*, arguments.next::<$type_>()?);
1664            ::std::result::Result::Ok(::std::option::Option::None)
1665        })
1666    };
1667    ($this:ty, ($($parameter:ty),*), $type_:ty; try_set: $set:expr $(, $($rest:tt)*)?) => {
1668        ::std::option::Option::Some(|arguments| {
1669            let mut arguments = $crate::metadata::MarkupArguments::new(
1670                arguments,
1671                2 + <[()]>::len(&[$($crate::__ferro_markup_unit!($parameter)),*]),
1672            )?;
1673            let this = arguments.next::<$this>()?;
1674            let _ = $crate::metadata::markup_result(
1675                ($set)(&this $(, arguments.next::<$parameter>()?)*, arguments.next::<$type_>()?),
1676            )?;
1677            ::std::result::Result::Ok(::std::option::Option::None)
1678        })
1679    };
1680    ($this:ty, ($($parameter:ty),*), $type_:ty; get: $get:expr $(, $($rest:tt)*)?) => {
1681        $crate::__ferro_markup_indexer_setter!($this, ($($parameter),*), $type_; $($($rest)*)?)
1682    };
1683    ($this:ty, ($($parameter:ty),*), $type_:ty; try_get: $get:expr $(, $($rest:tt)*)?) => {
1684        $crate::__ferro_markup_indexer_setter!($this, ($($parameter),*), $type_; $($($rest)*)?)
1685    };
1686}
1687
1688/// `Name, Name(args..), ..` as a constant slice of `MarkupAttribute`.
1689#[doc(hidden)]
1690#[macro_export]
1691macro_rules! __ferro_markup_attributes {
1692    ([$($done:expr,)*]) => {
1693        &[$($done),*]
1694    };
1695    ([$($done:expr,)*] $name:ident ($($arguments:tt)*) $(, $($rest:tt)*)?) => {
1696        $crate::__ferro_markup_attributes!([$($done,)* $crate::metadata::MarkupAttribute {
1697            name: ::std::stringify!($name),
1698            arguments: $crate::__ferro_markup_attribute_arguments!([] $($arguments)*),
1699            properties: $crate::__ferro_markup_attribute_properties!([] $($arguments)*),
1700        },] $($($rest)*)?)
1701    };
1702    ([$($done:expr,)*] $name:ident $(, $($rest:tt)*)?) => {
1703        $crate::__ferro_markup_attributes!([$($done,)* $crate::metadata::MarkupAttribute {
1704            name: ::std::stringify!($name),
1705            arguments: &[],
1706            properties: &[],
1707        },] $($($rest)*)?)
1708    };
1709}
1710
1711/// The positional arguments of an attribute declaration.
1712#[doc(hidden)]
1713#[macro_export]
1714macro_rules! __ferro_markup_attribute_arguments {
1715    ([$($done:expr,)*]) => {
1716        &[$($done),*]
1717    };
1718    // Named arguments are skipped.
1719    ([$($done:expr,)*] $key:ident = type($type_:ty) $(, $($rest:tt)*)?) => {
1720        $crate::__ferro_markup_attribute_arguments!([$($done,)*] $($($rest)*)?)
1721    };
1722    ([$($done:expr,)*] $key:ident = null $(, $($rest:tt)*)?) => {
1723        $crate::__ferro_markup_attribute_arguments!([$($done,)*] $($($rest)*)?)
1724    };
1725    ([$($done:expr,)*] $key:ident = [$($items:tt)*] $(, $($rest:tt)*)?) => {
1726        $crate::__ferro_markup_attribute_arguments!([$($done,)*] $($($rest)*)?)
1727    };
1728    ([$($done:expr,)*] $key:ident = $value:literal $(, $($rest:tt)*)?) => {
1729        $crate::__ferro_markup_attribute_arguments!([$($done,)*] $($($rest)*)?)
1730    };
1731    // An array: its items are positional arguments themselves.
1732    ([$($done:expr,)*] [$($items:tt)*] $(, $($rest:tt)*)?) => {
1733        $crate::__ferro_markup_attribute_arguments!([$($done,)*
1734            $crate::metadata::MarkupAttributeValue::Array(
1735                $crate::__ferro_markup_attribute_arguments!([] $($items)*)
1736            ),
1737        ] $($($rest)*)?)
1738    };
1739    ([$($done:expr,)*] type($type_:ty) $(, $($rest:tt)*)?) => {
1740        $crate::__ferro_markup_attribute_arguments!([$($done,)*
1741            $crate::metadata::MarkupAttributeValue::Type(|| $crate::data::core::ValueType::of::<$type_>()),
1742        ] $($($rest)*)?)
1743    };
1744    ([$($done:expr,)*] null $(, $($rest:tt)*)?) => {
1745        $crate::__ferro_markup_attribute_arguments!([$($done,)*
1746            $crate::metadata::MarkupAttributeValue::Null,
1747        ] $($($rest)*)?)
1748    };
1749    ([$($done:expr,)*] $value:literal $(, $($rest:tt)*)?) => {
1750        $crate::__ferro_markup_attribute_arguments!([$($done,)*
1751            $crate::metadata::MarkupLiteral($value).value(),
1752        ] $($($rest)*)?)
1753    };
1754}
1755
1756/// The named arguments of an attribute declaration.
1757#[doc(hidden)]
1758#[macro_export]
1759macro_rules! __ferro_markup_attribute_properties {
1760    ([$($done:expr,)*]) => {
1761        &[$($done),*]
1762    };
1763    ([$($done:expr,)*] $key:ident = type($type_:ty) $(, $($rest:tt)*)?) => {
1764        $crate::__ferro_markup_attribute_properties!([$($done,)* (
1765            ::std::stringify!($key),
1766            $crate::metadata::MarkupAttributeValue::Type(|| $crate::data::core::ValueType::of::<$type_>()),
1767        ),] $($($rest)*)?)
1768    };
1769    ([$($done:expr,)*] $key:ident = null $(, $($rest:tt)*)?) => {
1770        $crate::__ferro_markup_attribute_properties!([$($done,)* (
1771            ::std::stringify!($key),
1772            $crate::metadata::MarkupAttributeValue::Null,
1773        ),] $($($rest)*)?)
1774    };
1775    ([$($done:expr,)*] $key:ident = $value:literal $(, $($rest:tt)*)?) => {
1776        $crate::__ferro_markup_attribute_properties!([$($done,)* (
1777            ::std::stringify!($key),
1778            $crate::metadata::MarkupLiteral($value).value(),
1779        ),] $($($rest)*)?)
1780    };
1781    ([$($done:expr,)*] $key:ident = [$($items:tt)*] $(, $($rest:tt)*)?) => {
1782        $crate::__ferro_markup_attribute_properties!([$($done,)* (
1783            ::std::stringify!($key),
1784            $crate::metadata::MarkupAttributeValue::Array(
1785                $crate::__ferro_markup_attribute_arguments!([] $($items)*)
1786            ),
1787        ),] $($($rest)*)?)
1788    };
1789    // Positional arguments are skipped.
1790    ([$($done:expr,)*] [$($items:tt)*] $(, $($rest:tt)*)?) => {
1791        $crate::__ferro_markup_attribute_properties!([$($done,)*] $($($rest)*)?)
1792    };
1793    ([$($done:expr,)*] type($type_:ty) $(, $($rest:tt)*)?) => {
1794        $crate::__ferro_markup_attribute_properties!([$($done,)*] $($($rest)*)?)
1795    };
1796    ([$($done:expr,)*] null $(, $($rest:tt)*)?) => {
1797        $crate::__ferro_markup_attribute_properties!([$($done,)*] $($($rest)*)?)
1798    };
1799    ([$($done:expr,)*] $value:literal $(, $($rest:tt)*)?) => {
1800        $crate::__ferro_markup_attribute_properties!([$($done,)*] $($($rest)*)?)
1801    };
1802}
1803
1804/// The table of public Rust paths of the registered types of a crate, from
1805/// its generated `rust_paths.rs` (`scripts/rust_paths.py`, called by
1806/// `scripts/generate_markup_types.py`).
1807///
1808/// ```ignore
1809/// ferro_rust_paths! {
1810///     classes: [crate::Border, crate::primitives::Popup],
1811///     types: [crate::Dock, crate::GridLength],
1812///     contracts: [crate::templates::IDataTemplate],
1813/// }
1814/// ```
1815///
1816/// Every entry is a crate-relative public path; an instantiation of a
1817/// generic type (`generics`, `generic_contracts` for a trait) is the type
1818/// with every path absolute, and the path text the generator rendered for
1819/// it (checked from outside the crate by the XAML test crate). It defines
1820/// `CLASS_RUST_PATHS: &[(&TypeInfo, &str)]` (the runtime type of each
1821/// class) and `MARKUP_RUST_PATHS: &[(&MarkupType, &str, bool)]` (the
1822/// metadata of each type, of `dyn Trait` for a contract, and whether the
1823/// path names a trait), each with the path as another crate names it
1824/// (`crate` replaced by the name of the crate), and `TYPE_RUST_PATHS: &[(fn() -> TypeId, &str)]`
1825/// (the non-generic types by the `TypeId` of the type itself, for
1826/// [`register_type_rust_paths`](super::register_type_rust_paths)). The item and
1827/// the text come from the same tokens, so the text names exactly the
1828/// registered type. The crate passes both tables to
1829/// [`TypeInfo::register_rust_paths`](crate::TypeInfo::register_rust_paths)
1830/// and [`MarkupType::register_rust_paths`](super::MarkupType::register_rust_paths).
1831#[cfg(feature = "compiler-metadata")]
1832#[macro_export]
1833macro_rules! ferro_rust_paths {
1834    (
1835        classes: [$(crate $(:: $class:ident)+),* $(,)?],
1836        types: [$(crate $(:: $type_:ident)+),* $(,)?],
1837        contracts: [$(crate $(:: $contract:ident)+),* $(,)?],
1838        generics: [$(($generic:ty, $generic_path:literal)),* $(,)?],
1839        generic_contracts: [$(($generic_contract:path, $generic_contract_path:literal)),* $(,)?] $(,)?
1840    ) => {
1841        /// The public Rust paths of the classes of the type table.
1842        pub(crate) const CLASS_RUST_PATHS: &[(&'static $crate::TypeInfo, &'static str)] = &[$((
1843            <crate $(:: $class)+ as $crate::StaticType>::TYPE,
1844            ::std::concat!(::std::env!("CARGO_CRATE_NAME") $(, "::", ::std::stringify!($class))+),
1845        )),*];
1846
1847        /// The public Rust paths of the types, by the `TypeId` of the type itself.
1848        pub(crate) const TYPE_RUST_PATHS: &[(fn() -> ::std::any::TypeId, &'static str)] = &[
1849            $((
1850                || ::std::any::TypeId::of::<crate $(:: $class)+>(),
1851                ::std::concat!(::std::env!("CARGO_CRATE_NAME") $(, "::", ::std::stringify!($class))+),
1852            ),)*
1853            $((
1854                || ::std::any::TypeId::of::<crate $(:: $type_)+>(),
1855                ::std::concat!(::std::env!("CARGO_CRATE_NAME") $(, "::", ::std::stringify!($type_))+),
1856            ),)*
1857            $((
1858                || ::std::any::TypeId::of::<dyn crate $(:: $contract)+>(),
1859                ::std::concat!(::std::env!("CARGO_CRATE_NAME") $(, "::", ::std::stringify!($contract))+),
1860            ),)*
1861        ];
1862
1863        /// The public Rust paths of the markup types of the type lists.
1864        pub(crate) const MARKUP_RUST_PATHS: &[(&'static $crate::metadata::MarkupType, &'static str, bool)] = &[
1865            $((
1866                <crate $(:: $type_)+ as $crate::metadata::MarkupTyped>::MARKUP,
1867                ::std::concat!(::std::env!("CARGO_CRATE_NAME") $(, "::", ::std::stringify!($type_))+),
1868                false,
1869            ),)*
1870            $((
1871                <dyn crate $(:: $contract)+ as $crate::metadata::MarkupTyped>::MARKUP,
1872                ::std::concat!(::std::env!("CARGO_CRATE_NAME") $(, "::", ::std::stringify!($contract))+),
1873                true,
1874            ),)*
1875            $((<$generic as $crate::metadata::MarkupTyped>::MARKUP, $generic_path, false),)*
1876            $((<dyn $generic_contract as $crate::metadata::MarkupTyped>::MARKUP, $generic_contract_path, true),)*
1877        ];
1878
1879        /// Records the public Rust paths of this crate for the emitter of Rust source.
1880        pub(crate) fn register_rust_paths() {
1881            $crate::TypeInfo::register_rust_paths(CLASS_RUST_PATHS);
1882            $crate::metadata::register_type_rust_paths(TYPE_RUST_PATHS);
1883            $crate::metadata::MarkupType::register_rust_paths(MARKUP_RUST_PATHS);
1884        }
1885    };
1886}
1887
1888/// Without the `compiler-metadata` feature: `register_rust_paths()` records
1889/// nothing and the tables do not exist (see the other definition).
1890#[cfg(not(feature = "compiler-metadata"))]
1891#[macro_export]
1892macro_rules! ferro_rust_paths {
1893    ($($tokens:tt)*) => {
1894        /// Records the public Rust paths of this crate: nothing without the
1895        /// `compiler-metadata` feature of the base crate.
1896        pub(crate) fn register_rust_paths() {}
1897    };
1898}
1899
1900/// The tokens with the `markup-functions` feature of this crate (which
1901/// `compiler-metadata` enables), nothing without it: the typed functions of
1902/// declared members (`__markup_*`), which generated code calls.
1903#[cfg(feature = "markup-functions")]
1904#[doc(hidden)]
1905#[macro_export]
1906macro_rules! __ferro_markup_functions {
1907    ($($tokens:tt)*) => {
1908        $($tokens)*
1909    };
1910}
1911
1912/// Without the `markup-functions` feature: nothing (see the other
1913/// definition).
1914#[cfg(not(feature = "markup-functions"))]
1915#[doc(hidden)]
1916#[macro_export]
1917macro_rules! __ferro_markup_functions {
1918    ($($tokens:tt)*) => {};
1919}
1920
1921/// The tokens with the `compiler-metadata` feature of this crate, nothing
1922/// without it: what only the emitter of Rust source uses (the metadata that
1923/// names the typed functions, the public Rust paths). `@value
1924/// expr` is the value of a [`CompilerMetadata`](crate::metadata::CompilerMetadata)
1925/// slot: `expr` with the feature, the zero-sized stand-in without it.
1926#[cfg(feature = "compiler-metadata")]
1927#[doc(hidden)]
1928#[macro_export]
1929macro_rules! __ferro_compiler_metadata {
1930    (@value $value:expr) => {
1931        $value
1932    };
1933    ($($tokens:tt)*) => {
1934        $($tokens)*
1935    };
1936}
1937
1938/// Without the `compiler-metadata` feature: nothing (see the other
1939/// definition).
1940#[cfg(not(feature = "compiler-metadata"))]
1941#[doc(hidden)]
1942#[macro_export]
1943macro_rules! __ferro_compiler_metadata {
1944    (@value $value:expr) => {
1945        $crate::metadata::NotRecorded::new()
1946    };
1947    ($($tokens:tt)*) => {};
1948}