HasSchema

Derive Macro 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”.

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(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.

§hash & eq attributes

In order for a Schema to implement Hash and Eq, the derive requires opt in attributes instead of the opt out attributes required for Clone and Default since you are more likely to leave Hash and Eq out than you are to implement it.

ⓘ
#[derive(HasSchema, Clone, Default, PartialEq, Eq, Hash)]
#[schema(hash, eq)]
struct DoesImplHashAndEq;

§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.