Derive Macro bones_lib::prelude::bones_schema::HasSchema

source ·
#[derive(HasSchema)]
{
    // Attributes available to this derive:
    #[schema]
    #[derive_type_data]
    #[type_data]
    #[schema_module]
}
Expand description

Derive macro for the HasSchema trait.

§Usage with #[repr(C)]

HasSchema works with the #[repr(C)] annotation to fully implement its features.

If there is no #[repr(C)] annotation, the SchemaKind of your type’s schema will be Opaque.

This means if you don’t know the kind of type, like in the case of a SchemaBox, you’ll be unable to read the fields.

This applies to bones’ lua scripting since SchemaBox is effectively the “lua type”. See SchemaBox.

If you intend a type to be opaque even though it has #[repr(C)] you can use #[schema(opaque)] to force an opaque schema representation.

Keep in mind, enums deriving HasSchema with a #[repr(C)] annotation must also specify an enum tag type like #[repr(C, u8)] where u8 could be either u16 or u32 if you need more than 256 enum variants.

§no_default & no_clone attributes

HasSchema derive requires the type to implement Default & Clone, if either of these cannot be implemented you can use the no_default & no_clone schema attributes respectively to ignore these requirements.

#[derive(HasSchema, Default)]
#[schema(no_clone)]
struct DoesntImplClone;

#[derive(HasSchema, Clone)]
#[schema(no_default)]
struct DoesntImplDefault;

The caveat for putting no_default on your type is that it cannot be created from a Schema. This is necessary if you want to create your type within a bones lua script.

Since the fields that need to be initialized to create a complete version of your type cannot be determined, Schema needs a default function to initialize the data properly.

The caveat for putting no_clone on your type is that it cannot be cloned in the form of a SchemaBox.

This is critical in the case of bones’ networking which will panic if your type is in the world and does not implement clone during the network rollback.

§type_data attribute

This attribute takes an expression and stores that value in what is basically a type keyed map accessible from your type’s Schema.

§derive_type_data attribute

This attribute is simply a shortcut equivalent to using the type_data attribute with any type’s FromType<YourHasSchemaType> implementation like so:

#[derive(HasSchema, Clone, Default)]
#[type_data(<OtherType as FromType<Data>>::from_type())]
struct Data;

Simply specify a type instead of an expression:

#[derive(HasSchema, Clone, Default)]
#[derive_type_data(OtherType)] // OtherType implements FromType<Data>
struct Data;

§Known Limitations

Currently it isn’t possible to construct a struct that contains itself. For example, this will not work:

#[derive(HasSchema)]
struct Data {
    others: Vec<Data>,
}

If this is a problem for your use-case, please open an issue.