finalize schema/data setup

Signed-off-by: Folling <mail@folling.io>
This commit is contained in:
Folling 2025-01-01 13:49:05 +01:00
parent 70820129ae
commit 195f51d3d0
Signed by: folling
SSH key fingerprint: SHA256:S9qEx5WCFFLK49tE/LKnKuJYM5sw+++Dn6qJbbyxnCY
89 changed files with 2324 additions and 6271 deletions

View file

@ -0,0 +1,48 @@
#pragma once
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
/// \file data.h
/// \author Folling <mail@folling.io>
/// \addtogroup values Values
IKARUS_BEGIN_HEADER
/// \brief Data stores the actual information of a value.
/// \details Data is schemaless and can store any kind of data. Only when the
/// data is combined with a schema does it become a value. \see value.h.
/// Given the complexity of data, they are transferred as json.
/// The json representation of a data is a map with the following keys:
/// - `type` The type of the data. \see IkarusValueDataType. Must be one of the
/// following:
/// - `Primitive` A primitive value. Has two additional key:
/// - `primitive` The type of the primitive. Must be one of the following:
/// - `data` The stored data. Must be either a bool, double, or string.
/// - `Constant` A constant value. Has no additional keys, as the constant
/// value is shared across all values.
/// - `List` A list of values. Has the following additional keys:
/// - `data` An array of stored data.
/// - `Map` A map of key-value pairs. Has the following additional keys:
/// - `data` An array of key-value pairs.
/// - `Tuple` A tuple of values. Has the following additional keys:
/// - `data` An array of stored data.
/// Note that each sub-data is also a data, allowing for arbitrarily nested data
/// structures.
struct IkarusValueData;
/// \brief The type of data.
enum IkarusValueDataType {
/// \brief A primitive value. \see IkarusValuePrimitiveType.
IkarusValueDataType_Primitive = 1,
/// \brief A list of values.
IkarusValueDataType_List = 2,
/// \brief A map of key-value pairs.
IkarusValueDataType_Map = 3,
/// \brief A tuple of values.
IkarusValueDataType_Tuple = 4,
};
IKARUS_END_HEADER

View file

@ -1,109 +0,0 @@
#pragma once
/// \file number_value.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/values/value_cardinality.h>
/// \addtogroup values Values
/// @{
IKARUS_BEGIN_HEADER
/// \brief A numeric value. For example "Age" or "Height".
struct IkarusNumberValue;
/// \brief Creates an empty number value.
/// \details If the cardinality is "Single", the value will be initialized with 0.0.
/// \param cardinality The cardinality of the value.
/// \param error_out \see errors.h
/// \return The value or null if an error occurs.
IKA_API IkarusNumberValue * ikarus_number_value_create(IkarusValueCardinality cardinality, IkarusErrorData * error_out);
/// \brief Fetches the underlying data of a number value at a specific index.
/// \param value The number value.
/// \pre \li Must not be null.
/// \param idx The index of the data to fetch.
/// \pre \li Must be less than the size of the value.
/// \param error_out \see errors.h
/// \return The underlying data or NaN if an error occurs.
IKA_API double ikarus_number_value_get(IkarusNumberValue const * value, size_t idx, IkarusErrorData * error_out);
/// \brief Fetches the size of the underlying data of a number value.
/// \param value The number value.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The size of the underlying data or 0 if an error occurs.
IKA_API size_t ikarus_number_value_get_size(IkarusNumberValue const * value, IkarusErrorData * error_out);
/// \brief Sets the data of a number value at a specific index.
/// \param value The number value.
/// \pre \li Must not be null.
/// \param idx The index of the data to set.
/// \pre \li Must be less than the size of the value.
/// \param new_data The new data.
/// \param error_out \see errors.h
IKA_API void ikarus_number_value_set(IkarusNumberValue * value, size_t idx, double new_data, IkarusErrorData * error_out);
/// \brief Inserts a data into a number value.
/// \param value The number value.
/// \pre \li Must not be null.
/// \pre \li Cardinality must be "Multiple".
/// \param idx The index of the data to insert.
/// \pre \li Must be less than or equal to the size of the value.
/// \param new_data The new data.
/// \param error_out \see errors.h
IKA_API void ikarus_number_value_insert(IkarusNumberValue * value, size_t idx, double new_data, IkarusErrorData * error_out);
/// \brief Removes a data from a number value.
/// \param value The number value.
/// \pre \li Must not be null.
/// \pre \li Cardinality must be "Multiple".
/// \param idx The index of the data to remove.
/// \pre \li Must be less than the size of the value.
/// \param error_out \see errors.h
IKA_API void ikarus_number_value_remove(IkarusNumberValue * value, size_t idx, IkarusErrorData * error_out);
/// \brief Clears a number value.
/// \param value The number value.
/// \pre \li Cardinality must be "Multiple".
/// \param error_out \see errors.h
IKA_API void ikarus_number_value_clear(IkarusNumberValue * value, IkarusErrorData * error_out);
/// \brief Converts a number value to a string.
/// \param value The number value to convert.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The converted string.
/// \remark Must be freed with #ikarus_free.
IKA_API char const * ikarus_number_value_to_string(IkarusNumberValue const * value, IkarusErrorData * error_out);
/// \brief Checks if two values are equal.
/// \param lhs The left hand side value.
/// \pre \li Must not be null.
/// \param rhs The right hand side value.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return True if the values' data are equal, false otherwise.
IKA_API bool ikarus_number_value_is_equal(IkarusNumberValue const * lhs, IkarusNumberValue const * rhs, IkarusErrorData * error_out);
/// \brief Creates a copy of a number value.
/// \param value The value to copy.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The copied value.
IKA_API IkarusNumberValue * ikarus_number_value_copy(IkarusNumberValue const * value, IkarusErrorData * error_out);
/// \brief Converts a number value to an entity value.
/// \param value The number value to convert.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The converted entity value.
/// \remark This is the same pointer, so freeing it implies freeing the original value.
IKA_API struct IkarusValueData * ikarus_number_value_to_value(IkarusNumberValue * value, IkarusErrorData * error_out);
IKARUS_END_HEADER
/// @}

View file

@ -0,0 +1,58 @@
#pragma once
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
/// \file schema.h
/// \author Folling <mail@folling.io>
/// \addtogroup values Values
IKARUS_BEGIN_HEADER
/// \brief Schemas define the type of value.
/// \details Schemas are used to define the type of value. They are akin to
/// classes in programming languages.
/// Schemas are used to validate values and structure data.
///
/// Given the complexity of schemas, they are transferred as json.
/// The json representation of a schema is a map with the following keys:
/// - `type` The type of the schema. Must be one of the following:
/// - `Primitive` A primitive value. Has the following additional keys:
/// - `primitive` The type of the primitive value. \see IkarusPrimitiveType.
/// - `Constant` A constant value. Has the following additional keys:
/// - `value` The constant value, shared across all values of the schema.
/// \see value.h. \remark The schema is derived from the value.
/// - `List` A list of values. Has the following additional keys:
/// - `schema` The schema of the values in the list.
/// - `Map` A map of key-value pairs. Has the following additional keys:
/// - `key_schema` The schema of the keys.
/// - `value_schema` The schema of the values.
/// - `Tuple` A tuple of values. Has the following additional keys:
/// - `schemas` The schemas of the values in the tuple.
struct IkarusSchema;
/// \brief The type of primitive data.
enum IkarusValuePrimitiveType {
/// \brief A boolean.
IkarusValuePrimitiveType_Toggle = 1,
/// \brief A 64-bit floating point number.
IkarusValuePrimitiveType_Number = 2,
/// \brief An arbitrary length string.
IkarusValuePrimitiveType_Text = 3
};
/// \brief The type of schema.
enum IkarusValueSchemaType {
/// \brief A primitive value. \see IkarusPrimitiveType
IkarusValueSchemaType_Primitive = 1,
/// \brief A homogeneous list of values.
IkarusValueSchemaType_List = 2,
/// \brief A mapping from Value->Value.
IkarusValueSchemaType_Map = 3,
/// \brief A heterogeneous list of values.
IkarusValueSchemaType_Tuple = 4
};
IKARUS_END_HEADER

View file

@ -1,109 +0,0 @@
#pragma once
/// \file text_value.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/values/value_cardinality.h>
/// \addtogroup values Values
/// @{
IKARUS_BEGIN_HEADER
/// \brief A numeric value. For example "Age" or "Height".
struct IkarusTextValue;
/// \brief Creates an empty text value.
/// \details If the cardinality is "Single", the value will be initialized with 0.0.
/// \param cardinality The cardinality of the value.
/// \param error_out \see errors.h
/// \return The value or null if an error occurs.
IKA_API IkarusTextValue * ikarus_text_value_create(IkarusValueCardinality cardinality, IkarusErrorData * error_out);
/// \brief Fetches the underlying data of a text value at a specific index.
/// \param value The text value.
/// \pre \li Must not be null.
/// \param idx The index of the data to fetch.
/// \pre \li Must be less than the size of the value.
/// \param error_out \see errors.h
/// \return The underlying data or NaN if an error occurs.
IKA_API char const * ikarus_text_value_get(IkarusTextValue const * value, size_t idx, IkarusErrorData * error_out);
/// \brief Fetches the size of the underlying data of a text value.
/// \param value The text value.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The size of the underlying data or 0 if an error occurs.
IKA_API size_t ikarus_text_value_get_size(IkarusTextValue const * value, IkarusErrorData * error_out);
/// \brief Sets the data of a text value at a specific index.
/// \param value The text value.
/// \pre \li Must not be null.
/// \param idx The index of the data to set.
/// \pre \li Must be less than the size of the value.
/// \param new_data The new data.
/// \param error_out \see errors.h
IKA_API void ikarus_text_value_set(IkarusTextValue * value, size_t idx, char const * new_data, IkarusErrorData * error_out);
/// \brief Inserts a data into a text value.
/// \param value The text value.
/// \pre \li Must not be null.
/// \pre \li Cardinality must be "Multiple".
/// \param idx The index of the data to insert.
/// \pre \li Must be less than or equal to the size of the value.
/// \param new_data The new data.
/// \param error_out \see errors.h
IKA_API void ikarus_text_value_insert(IkarusTextValue * value, size_t idx, char const * new_data, IkarusErrorData * error_out);
/// \brief Removes a data from a text value.
/// \param value The text value.
/// \pre \li Must not be null.
/// \pre \li Cardinality must be "Multiple".
/// \param idx The index of the data to remove.
/// \pre \li Must be less than the size of the value.
/// \param error_out \see errors.h
IKA_API void ikarus_text_value_remove(IkarusTextValue * value, size_t idx, IkarusErrorData * error_out);
/// \brief Clears a text value.
/// \param value The text value.
/// \pre \li Cardinality must be "Multiple".
/// \param error_out \see errors.h
IKA_API void ikarus_text_value_clear(IkarusTextValue * value, IkarusErrorData * error_out);
/// \brief Converts a text value to a string.
/// \param value The text value to convert.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The converted string.
/// \remark Must be freed with #ikarus_free.
IKA_API char const * ikarus_text_value_to_string(IkarusTextValue const * value, IkarusErrorData * error_out);
/// \brief Checks if two values are equal.
/// \param lhs The left hand side value.
/// \pre \li Must not be null.
/// \param rhs The right hand side value.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return True if the values' data are equal, false otherwise.
IKA_API bool ikarus_text_value_is_equal(IkarusTextValue const * lhs, IkarusTextValue const * rhs, IkarusErrorData * error_out);
/// \brief Creates a copy of a text value.
/// \param value The value to copy.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The copied value.
IKA_API IkarusTextValue * ikarus_text_value_copy(IkarusTextValue const * value, IkarusErrorData * error_out);
/// \brief Converts a text value to an entity value.
/// \param value The text value to convert.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The converted entity value.
/// \remark This is the same pointer, so freeing it implies freeing the original value.
IKA_API struct IkarusValueData * ikarus_text_value_to_value(IkarusTextValue * value, IkarusErrorData * error_out);
IKARUS_END_HEADER
/// @}

View file

@ -1,109 +0,0 @@
#pragma once
/// \file toggle_value.h
/// \author Folling <folling@ikarus.world>
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/values/value_cardinality.h>
/// \addtogroup values Values
/// @{
IKARUS_BEGIN_HEADER
/// \brief A numeric value. For example "Age" or "Height".
struct IkarusToggleValue;
/// \brief Creates an empty toggle value.
/// \details If the cardinality is "Single", the value will be initialized with 0.0.
/// \param cardinality The cardinality of the value.
/// \param error_out \see errors.h
/// \return The value or null if an error occurs.
IKA_API IkarusToggleValue * ikarus_toggle_value_create(IkarusValueCardinality cardinality, IkarusErrorData * error_out);
/// \brief Fetches the underlying data of a toggle value at a specific index.
/// \param value The toggle value.
/// \pre \li Must not be null.
/// \param idx The index of the data to fetch.
/// \pre \li Must be less than the size of the value.
/// \param error_out \see errors.h
/// \return The underlying data or NaN if an error occurs.
IKA_API bool ikarus_toggle_value_get(IkarusToggleValue const * value, size_t idx, IkarusErrorData * error_out);
/// \brief Fetches the size of the underlying data of a toggle value.
/// \param value The toggle value.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The size of the underlying data or 0 if an error occurs.
IKA_API size_t ikarus_toggle_value_get_size(IkarusToggleValue const * value, IkarusErrorData * error_out);
/// \brief Sets the data of a toggle value at a specific index.
/// \param value The toggle value.
/// \pre \li Must not be null.
/// \param idx The index of the data to set.
/// \pre \li Must be less than the size of the value.
/// \param new_data The new data.
/// \param error_out \see errors.h
IKA_API void ikarus_toggle_value_set(IkarusToggleValue * value, size_t idx, bool new_data, IkarusErrorData * error_out);
/// \brief Inserts a data into a toggle value.
/// \param value The toggle value.
/// \pre \li Must not be null.
/// \pre \li Cardinality must be "Multiple".
/// \param idx The index of the data to insert.
/// \pre \li Must be less than or equal to the size of the value.
/// \param new_data The new data.
/// \param error_out \see errors.h
IKA_API void ikarus_toggle_value_insert(IkarusToggleValue * value, size_t idx, bool new_data, IkarusErrorData * error_out);
/// \brief Removes a data from a toggle value.
/// \param value The toggle value.
/// \pre \li Must not be null.
/// \pre \li Cardinality must be "Multiple".
/// \param idx The index of the data to remove.
/// \pre \li Must be less than the size of the value.
/// \param error_out \see errors.h
IKA_API void ikarus_toggle_value_remove(IkarusToggleValue * value, size_t idx, IkarusErrorData * error_out);
/// \brief Clears a toggle value.
/// \param value The toggle value.
/// \pre \li Cardinality must be "Multiple".
/// \param error_out \see errors.h
IKA_API void ikarus_toggle_value_clear(IkarusToggleValue * value, IkarusErrorData * error_out);
/// \brief Converts a toggle value to a string.
/// \param value The toggle value to convert.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The converted string.
/// \remark Must be freed with #ikarus_free.
IKA_API char const * ikarus_toggle_value_to_string(IkarusToggleValue const * value, IkarusErrorData * error_out);
/// \brief Checks if two values are equal.
/// \param lhs The left hand side value.
/// \pre \li Must not be null.
/// \param rhs The right hand side value.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return True if the values' data are equal, false otherwise.
IKA_API bool ikarus_toggle_value_is_equal(IkarusToggleValue const * lhs, IkarusToggleValue const * rhs, IkarusErrorData * error_out);
/// \brief Creates a copy of a toggle value.
/// \param value The value to copy.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The copied value.
IKA_API IkarusToggleValue * ikarus_toggle_value_copy(IkarusToggleValue const * value, IkarusErrorData * error_out);
/// \brief Converts a toggle value to an entity value.
/// \param value The toggle value to convert.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The converted entity value.
/// \remark This is the same pointer, so freeing it implies freeing the original value.
IKA_API struct IkarusValueData * ikarus_toggle_value_to_value(IkarusToggleValue * value, IkarusErrorData * error_out);
IKARUS_END_HEADER
/// @}

View file

@ -1,61 +1,26 @@
#pragma once
/// \file value.h
/// \author Folling <folling@ikarus.world>
/// \defgroup values Values
/// \brief Values are data in entities.
/// \details An entity is made up of any number of values.
/// Each value defines a certain aspect of an entity.
/// Values have a name, a type, and some data.
/// Examples of values would be:
/// - Is Dead (Toggle)
/// - Age (Number)
/// - ISBN (Text)
///
/// Values are either single or multiple.
/// We call this property "Cardinality" (\see IkarusValueCardinality)
/// because it's really hard to find a simpler name.
/// Each piece of data within a value is called a "datapoint".
/// Single values have exactly one datapoint, multiple values have any number of
/// datapoints. For example "Age" would be singular, while "Nicknames" would be
/// multiple. The type is unaffected by this. A pendant in programming languages
/// would be a List<T>. Note that all values are stored as a list of items,
/// even if the value is singular. Single values effectively act as a list with
/// one element. This is enforced by the API at runtime.
///
/// For a comprehensive list of value types, see \ref IkarusValueType.
/// @{
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
/// \file value.h
/// \author Folling <mail@folling.io>
/// \defgroup entities Entities
/// \brief Entities are the core building blocks of Ikarus.
IKARUS_BEGIN_HEADER
/// \brief The common type for all value data.
struct IkarusValue;
/// \brief Visits an entity value,
/// calling the appropriate function for the value's type.
/// \param value The entity value to visit.
/// \pre \li Must not be null.
/// \param toggle_visitor The function to call if the value is a toggle value.
/// \remark Skipped if null.
/// \param number_visitor The function to call if the value is a number value.
/// \remark Skipped if null.
/// \param text_visitor The function to call if the value is a text value.
/// \remark Skipped if null.
/// \param data The data passed to the visitor functions.
/// \param error_out \see errors.h
IKA_API void ikarus_value_visit(
IkarusValue * value,
void (*toggle_visitor)(struct IkarusToggleValue *, void *),
void (*number_visitor)(struct IkarusNumberValue *, void *),
void (*text_visitor)(struct IkarusTextValue *, void *),
void * data,
IkarusErrorData * error_out
);
/// \brief Values are data containers for entities.
/// \details Values are flexible enough to store any kind of data. They are
/// akin to objects in programming languages.
/// Each value has a schema that defines the type of the value. \see schema.h
/// They also store data appropriate for the schema.
///
/// Given the complexity of values, they are transferred as json.
/// The json representation of a value is a map with the following keys:
/// - `schema`: The schema of the value. \see schema.h.
/// - `data`: The data of the value. \see data.h.
IKARUS_END_HEADER
/// @}

View file

@ -1,23 +0,0 @@
#pragma once
/// \file value_cardinality.h
/// \author Folling <folling@ikarus.world>
/// \addtogroup values Values
/// @{
#include <ikarus/macros.h>
IKARUS_BEGIN_HEADER
/// \brief The cardinality of a value.
enum IkarusValueCardinality {
/// \brief Only contains one datapoint
IkarusValueCardinality_Single,
/// \brief Contains any number of datapoints
IkarusValueCardinality_List
};
IKARUS_END_HEADER
/// @}

View file

@ -1,198 +0,0 @@
#pragma once
/// \file value_schema.h
/// \author Folling <folling@ikarus.world>
/// \addtogroup values Values
/// @{
#include <ikarus/errors.h>
#include <ikarus/macros.h>
#include <ikarus/stdtypes.h>
IKARUS_BEGIN_HEADER
/// \brief Layouts define the structure and constraints of values.
/// \details Ikarus lets you define any schema for values and add constraints to them.
/// These schemas are assembled hierarchical and are akin to JSON schemas.
/// Layouts may be arbitrarily nested and combined e.g.:
/// Combination<List<Text>, Number, Complex<"Foo":Toggle,"Bar":Text>
struct IkarusValueLayout;
/// \brief A fixed datapoint with a fixed layout.
/// Example: Age: Union<Number, Constant<Text, "Dead">>
struct IkarusValueLayoutConstant;
/// \brief A singular datapoint with one of a list of layouts.
/// Example: ChestReward: Combination<Item, Gold, Mimic>
struct IkarusValueLayoutCombination;
/// \brief A collection of datapoints with a homogenous layout.
/// Example: Friends: List<Character>
struct IkarusValueLayoutList;
/// \brief A collection of nameable datapoints with heterogeneous layouts.
/// Example: GeoLocation: Complex<"Latitude":Number, "Longitude":Number>
struct IkarusValueLayoutComplex;
/// \brief Defines the type of datapoints.
enum IkarusValueDataType {
/// \brief Boolean datapoints
/// Example: Is the character alive? Yes
Toggle,
/// \brief Numeric datapoints
/// Example: How much does the character weigh? 57kg
Number,
/// \brief Textual datapoints
/// Example: What is the character's maiden name? Sandra
Text,
/// \brief A colour datapoint
/// Example: What colours make up the nation's flag? White/Pink/Blue.
/// \remark Not yet implemented
Colour,
/// \brief A date/time datapoint, interfacing with the calendar and timeline feature.
/// Example: When was the city founded? 12th of January 233 at 2:11
/// \remark Not yet implemented
Time,
/// \brief A location datapoint, interfacing with the map feature.
/// Example: Where is the city situated? 12.345, 67.890
/// \remark Not yet implemented
Location,
/// \brief An enum-esque datapoint
/// Example: Of which rarity is the weapon? Normal/Rare/Legendary
/// \remark Not yet implemented
Choice,
/// \brief A datapoint linking to some other object in Ikarus
/// Example: Who wrote this hymn? Peter Parker
/// \remark Not yet implemented
Reference
};
/// \brief Stores either a schema or a datatype
struct IkarusValueSchema;
/// \see ikarus_value_schema_from_layout_const
IkarusValueSchema * ikarus_value_schema_from_layout(
IkarusValueLayout * layout,
IkarusErrorData * error_out
);
/// \brief Creates a value schema from a layout.
/// \param layout The layout to create the schema from.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The created schema or null if an error occurs.
IkarusValueSchema const * ikarus_value_schema_from_layout_const(
IkarusValueLayout const * layout,
IkarusErrorData * error_out
);
/// \brief Creates a value schema from a datatype.
/// \param type The datatype to create the schema from.
/// \param error_out \see errors.h
/// \return The created schema or null if an error occurs.
IkarusValueSchema * ikarus_value_schema_from_data_type(
IkarusValueDataType type,
IkarusErrorData * error_out
);
/// \brief Frees a value schema.
/// \param schema The schema to free.
/// \pre \li Must not be null.
/// \remark Must not be accessed after freeing.
void ikarus_value_schema_free(IkarusValueSchema * schema);
/// \see ikarus_value_schema_visit_const
void ikarus_value_schema_visit(
IkarusValueSchema * schema,
void (*layout_visitor)(IkarusValueLayout * layout),
void (*data_type_visitor)(IkarusValueDataType type),
IkarusErrorData * error_out
);
/// \brief Visits a value schema.
/// \param schema The schema to visit.
/// \pre \li Must not be null.
/// \param layout_visitor The function to call if the schema is a layout. Skipped if null.
/// \param data_type_visitor The function to call if the schema is a datatype. Skipped if null.
void ikarus_value_schema_visit_const(
IkarusValueSchema const * schema,
void (*layout_visitor)(IkarusValueLayout const * layout),
void (*data_type_visitor)(IkarusValueDataType type),
IkarusErrorData * error_out
);
/// \brief Creates a constant layout.
/// \param schema The schema of the value.
/// \pre \li Must not be null.
/// \param value The value of the constant.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
IkarusValueLayoutConstant * ikarus_value_layout_constant_create(
IkarusValueSchema * schema,
struct IkarusValue * value,
IkarusErrorData * error_out
);
/// \brief Gets the underyling schema of a constant layout.
/// \param layout The layout to get the underyling schema of.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The underlying schema of the layout or null if an error occurs.
IkarusValueSchema const * ikarus_value_layout_constant_get_underyling_schema(
IkarusValueLayoutConstant const * layout,
IkarusErrorData * error_out
);
/// \brief Gets the underyling value of a constant layout.
/// \param layout The layout to get the underyling value of.
/// \pre \li Must not be null.
/// \param error_out \see errors.h
/// \return The underlying value of the layout or null if an error occurs.
struct IkarusValue const * ikarus_value_layout_constant_get_underlying_value(
IkarusValueLayoutConstant const * layout,
IkarusErrorData * error_out
);
/// \brief Creates a combination layout.
/// \param schemas The schemas of the values.
/// \pre \li Must not be null.
/// \param schemas_size The number of schemas.
/// \param error_out \see errors.h
/// \return The created layout or null if an error occurs.
/// \remark The schemas are copied.
IkarusValueLayoutCombination * ikarus_value_layout_combination_create(
IkarusValueSchema * schemas,
size_t schemas_size,
IkarusErrorData * error_out
);
void ikarus_value_layout_combination_get_schemas(
IkarusValueLayoutCombination const * layout,
IkarusValueSchema ** schemas_out,
size_t * schemas_size_out,
IkarusErrorData * error_out
);
size_t ikarus_value_layout_combination_get_schemas_count(
IkarusValueLayoutCombination const * layout,
IkarusErrorData * error_out
);
IkarusValueLayoutList * ikarus_value_layout_list_create(
IkarusValueSchema * schema,
IkarusErrorData * error_out
);
IkarusValueLayoutComplex * ikarus_value_layout_complex_create(
IkarusValueSchema * schemas,
size_t schemas_size,
IkarusErrorData * error_out
);
IkarusValueLayoutComplex * ikarus_value_layout_complex_create_named(
IkarusValueSchema * schemas,
char const ** names,
size_t schemas_size,
IkarusErrorData * error_out
);
IKARUS_END_HEADER
/// @}