summaryrefslogtreecommitdiff
path: root/src/core/model
diff options
context:
space:
mode:
authorAndreas Stöckel <astoecke@techfak.uni-bielefeld.de>2014-12-28 00:54:05 +0100
committerAndreas Stöckel <andreas@somweyr.de>2014-12-28 00:54:05 +0100
commit3f22fdbf6aa5d4543c122a91cf244046697a1ec9 (patch)
treea4ea51b9147d7773a5fa1d5fb1bbac3f644082ec /src/core/model
parent079b45a6745dc296a60622d5a4897ccdfcf1fa0f (diff)
Finished StructType implementation, started to write unit tests
Diffstat (limited to 'src/core/model')
-rw-r--r--src/core/model/Typesystem.cpp251
-rw-r--r--src/core/model/Typesystem.hpp291
2 files changed, 441 insertions, 101 deletions
diff --git a/src/core/model/Typesystem.cpp b/src/core/model/Typesystem.cpp
index c2ab363..4a2f4eb 100644
--- a/src/core/model/Typesystem.cpp
+++ b/src/core/model/Typesystem.cpp
@@ -26,44 +26,44 @@ namespace model {
/* Class Type */
-bool Type::build(Variant &var, Logger &logger) const
+bool Type::build(Variant &data, Logger &logger) const
{
try {
- return doBuild(var, logger);
+ return doBuild(data, logger);
}
catch (LoggableException ex) {
logger.log(ex);
- var = create();
+ data = create();
return false;
}
}
/* Class StringType */
-bool StringType::doBuild(Variant &var, Logger &logger) const
+bool StringType::doBuild(Variant &data, Logger &logger) const
{
// Cannot convert non-primitive values to strings
- if (!var.isPrimitive()) {
+ if (!data.isPrimitive()) {
throw LoggableException{"Expected a string or primitive input."};
}
// Perform an implicit type conversion
- if (!var.isString() || var.isMagic()) {
+ if (!data.isString() || data.isMagic()) {
// Convert the variant value to a string and set it
- var = var.toString().c_str();
+ data = data.toString().c_str();
// Log conversions as these may be potentially unwanted
logger.note(std::string("Implicit conversion from ") +
- var.getTypeName() + " to string.");
+ data.getTypeName() + " to string.");
}
return true;
}
/* Class IntType */
-bool IntType::doBuild(Variant &var, Logger &logger) const
+bool IntType::doBuild(Variant &data, Logger &logger) const
{
- if (!var.isInt()) {
+ if (!data.isInt()) {
throw LoggableException{"Expected an integer value."};
}
return true;
@@ -71,20 +71,20 @@ bool IntType::doBuild(Variant &var, Logger &logger) const
/* Class DoubleType */
-bool DoubleType::doBuild(Variant &var, Logger &logger) const
+bool DoubleType::doBuild(Variant &data, Logger &logger) const
{
- if (!var.isInt() && !var.isDouble()) {
+ if (!data.isInt() && !data.isDouble()) {
throw LoggableException{"Expected a double value."};
}
- var = Variant{var.toDouble()};
+ data = Variant{data.toDouble()};
return true;
}
/* Class BoolType */
-bool BoolType::doBuild(Variant &var, Logger &logger) const
+bool BoolType::doBuild(Variant &data, Logger &logger) const
{
- if (!var.isBool()) {
+ if (!data.isBool()) {
throw LoggableException("Expected boolean value!");
}
return true;
@@ -92,11 +92,11 @@ bool BoolType::doBuild(Variant &var, Logger &logger) const
/* Class EnumType */
-bool EnumType::doBuild(Variant &var, Logger &logger) const
+bool EnumType::doBuild(Variant &data, Logger &logger) const
{
// If the variant is an int, check whether the value is in range
- if (var.isInt()) {
- int i = var.asInt();
+ if (data.isInt()) {
+ int i = data.asInt();
if (i < 0 || i >= (int)values.size()) {
throw LoggableException("Value is out of range.");
}
@@ -105,9 +105,9 @@ bool EnumType::doBuild(Variant &var, Logger &logger) const
// If the given variant is a magic value it may be an enumeration constant.
// Set the variant to the numeric value
- if (var.isMagic()) {
+ if (data.isMagic()) {
// Fetch the given constant name and look it up in the value map
- const std::string &name = var.asMagic();
+ const std::string &name = data.asMagic();
auto it = values.find(name);
// Throw an execption if the given string value is not found
@@ -115,16 +115,15 @@ bool EnumType::doBuild(Variant &var, Logger &logger) const
throw LoggableException(std::string("Unknown enum constant: \"") +
name + std::string("\""));
}
- var = it->second;
+ data = it->second;
return true;
}
throw LoggableException{"Expected integer or identifier"};
}
-Rooted<EnumType> EnumType::createValidated(Manager &mgr, std::string name,
- Handle<Typesystem> system,
- const std::vector<std::string> &values,
- Logger &logger)
+Rooted<EnumType> EnumType::createValidated(
+ Manager &mgr, std::string name, Handle<Typesystem> system,
+ const std::vector<std::string> &values, Logger &logger)
{
// Map used to store the unique values of the enum
std::map<std::string, Ordinal> unique_values;
@@ -170,15 +169,211 @@ EnumType::Ordinal EnumType::valueOf(const std::string &name) const
throw LoggableException(std::string("Unknown enum constant: ") + name);
}
+/* Class StructType */
+
+bool StructType::resolveIndexKey(const std::string &key, size_t &idx) const
+{
+ try {
+ idx = stoul(key.substr(1));
+ return true;
+ }
+ catch (std::exception ex) {
+ return false;
+ }
+}
+
+bool StructType::resolveIdentifierKey(const std::string &key, size_t &idx) const
+{
+ auto it = attributeNames.find(key);
+ if (it == attributeNames.end()) {
+ return false;
+ }
+ idx = it->second;
+ return true;
+}
+
+bool StructType::resolveKey(const std::string &key, size_t &idx) const
+{
+ bool res;
+ if (!key.empty() && key[0] == '#') {
+ res = resolveIndexKey(key, idx);
+ } else {
+ res = resolveIdentifierKey(key, idx);
+ }
+ return res && (idx < attributes.size());
+}
+
+bool StructType::insertDefaults(Variant &data, const std::vector<bool> &set,
+ Logger &logger) const
+{
+ bool ok = true;
+ Variant::arrayType &arr = data.asArray();
+ for (size_t a = 0; a < arr.size(); a++) {
+ if (!set[a]) {
+ if (attributes[a]->optional) {
+ arr[a] = attributes[a]->defaultValue;
+ } else {
+ ok = false;
+ arr[a] = attributes[a]->getType()->create();
+ logger.error(std::string("Expected attribute ") +
+ attributes[a]->getName() +
+ std::string(", but no value given."));
+ }
+ }
+ }
+ return ok;
+}
+
+bool StructType::buildFromArray(Variant &data, Logger &logger, bool trim) const
+{
+ bool ok = true;
+ Variant::arrayType &arr = data.asArray();
+ std::vector<bool> set;
+
+ // Fetch the size of the input array n and the number of attributes N
+ const size_t n = arr.size();
+ const size_t N = attributes.size();
+ arr.resize(N);
+ set.resize(N);
+
+ // Make sure the array has the correct size
+ if (n > N && !trim) {
+ ok = false;
+ logger.error(std::string("Expected at most ") + std::to_string(N) +
+ std::string(" attributes, but got ") + std::to_string(n));
+ }
+
+ // Make sure the given attributes have to correct type
+ for (size_t a = 0; a < n; a++) {
+ set[a] = attributes[a]->getType()->build(arr[a], logger);
+ ok = ok && set[a];
+ }
+
+ return insertDefaults(data, set, logger) && ok;
+}
+
+bool StructType::buildFromMap(Variant &data, Logger &logger, bool trim) const
+{
+ bool ok = true;
+ const Variant::mapType &map = data.asMap();
+ Variant::arrayType arr;
+ std::vector<bool> set;
+
+ // Fetch the size of the input map n and the number of attributes N
+ const size_t N = attributes.size();
+ arr.resize(N);
+ set.resize(N);
+
+ // Iterate over the map entries
+ for (auto &m : map) {
+ // Fetch key and value
+ const std::string &key = m.first;
+ const Variant &value = m.second;
+
+ // Lookup the key index
+ size_t idx = 0;
+ if (resolveKey(key, idx)) {
+ // Warn about overriding the same key
+ if (set[idx]) {
+ logger.warning(
+ std::string("Attribute \"") + key +
+ std::string("\" set multiple times, overriding!"));
+ }
+
+ // Convert the value to the type of the attribute
+ arr[idx] = value;
+ set[idx] = attributes[idx]->getType()->build(arr[idx], logger);
+ } else if (!trim) {
+ ok = false;
+ logger.error(std::string("Invalid attribute key \"") + key +
+ std::string("\""));
+ }
+ }
+
+ // Copy the built array to the result and insert missing default values
+ data = arr;
+ return insertDefaults(data, set, logger) && ok;
+}
+
+bool StructType::buildFromArrayOrMap(Variant &data, Logger &logger,
+ bool trim) const
+{
+ if (data.isArray()) {
+ return buildFromArray(data, logger, trim);
+ }
+ if (data.isMap()) {
+ return buildFromMap(data, logger, trim);
+ }
+ throw LoggableException(
+ "Expected array or map for building a struct type!");
+}
+
+bool StructType::doBuild(Variant &data, Logger &logger) const
+{
+ return buildFromArrayOrMap(data, logger, false);
+}
+
+Rooted<StructType> StructType::createValidated(
+ Manager &mgr, std::string name, Handle<Typesystem> system,
+ Handle<StructType> parent, NodeVector<Attribute> attributes, Logger &logger)
+{
+ // Check the attributes for validity and uniqueness
+ std::map<std::string, size_t> attributeNames;
+ for (size_t idx = 0; idx < attributes.size(); idx++) {
+ // Check for valid attribute names
+ const std::string &attrName = attributes[idx]->getName();
+ if (!Utils::isIdentifier(name)) {
+ logger.error(std::string("Invalid attribute name \"") + name +
+ std::string("\""));
+ }
+
+ // Check for uniqueness
+ auto res = attributeNames.emplace(attrName, idx);
+ if (!res.second) {
+ logger.error(std::string("Attribute with name \"") + name +
+ std::string("\" defined multiple times"));
+ }
+ }
+
+ // Call the private constructor
+ return new StructType(mgr, name, system, parent, attributes, attributeNames);
+}
+
+Variant StructType::create() const
+{
+ Variant::arrayType arr;
+ arr.resize(attributes.size());
+ for (size_t idx = 0; idx < attributes.size(); idx++) {
+ arr[idx] = attributes[idx]->getType()->create();
+ }
+ return arr;
+}
+
+bool StructType::derivedFrom(Handle<StructType> other) const
+{
+ if (other == this) {
+ return true;
+ }
+ if (parent != nullptr) {
+ return parent->derivedFrom(other);
+ }
+ return false;
+}
+
+Variant StructType::cast(Variant &data, Logger &logger) const
+{
+ return buildFromArrayOrMap(data, logger, true);
+}
+
/* Class ArrayType */
-bool ArrayType::doBuild(Variant &var, Logger &logger) const
+bool ArrayType::doBuild(Variant &data, Logger &logger) const
{
- if (!var.isArray()) {
+ if (!data.isArray()) {
throw LoggableException("Expected array!");
}
bool res = true;
- for (auto &v : var.asArray()) {
+ for (auto &v : data.asArray()) {
if (!innerType->build(v, logger)) {
res = false;
}
diff --git a/src/core/model/Typesystem.hpp b/src/core/model/Typesystem.hpp
index 8562546..7eedc67 100644
--- a/src/core/model/Typesystem.hpp
+++ b/src/core/model/Typesystem.hpp
@@ -76,13 +76,13 @@ protected:
* an LoggableException in case the given data cannot be converted to
* the internal representation given by the type descriptor.
*
- * @param var is a variant containing the data that should be checked and
+ * @param data is a variant containing the data that should be checked and
* -- if possible and necessary -- converted to a variant adhering to the
* internal representation used by the Type class.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- virtual bool doBuild(Variant &var, Logger &logger) const = 0;
+ virtual bool doBuild(Variant &data, Logger &logger) const = 0;
public:
/**
@@ -102,13 +102,13 @@ public:
* Validates and completes the given variant which was read from a
* user-supplied source.
*
- * @param var is a variant containing the data that should be checked and
+ * @param data is a variant containing the data that should be checked and
* -- if possible and necessary -- converted to a variant adhering to the
* internal representation used by the Type class.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool build(Variant &var, Logger &logger) const;
+ bool build(Variant &data, Logger &logger) const;
/**
* Returns the underlying Typesystem instance.
@@ -132,12 +132,12 @@ protected:
* If possible, converts the given variant to a string. Only works, if the
* variant contains primitive objects (integers, strings, booleans, etc.).
*
- * @param var is a variant containing the data that should be checked and
+ * @param data is a variant containing the data that should be checked and
* converted to a string.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &var, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger) const override;
public:
/**
@@ -171,11 +171,11 @@ protected:
* Expects the given variant to be an integer. Does not perform any type
* conversion.
*
- * @param var is a variant containing the data that should be checked.
+ * @param data is a variant containing the data that should be checked.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &var, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger) const override;
public:
/**
@@ -209,11 +209,11 @@ protected:
* Expects the given variant to be a double or an integer. Converts integers
* to doubles.
*
- * @param var is a variant containing the data that should be checked.
+ * @param data is a variant containing the data that should be checked.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &var, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger) const override;
public:
/**
@@ -247,11 +247,11 @@ protected:
* Expects the given variant to be a boolean. Performs no implicit type
* conversion.
*
- * @param var is a variant containing the data that should be checked.
+ * @param data is a variant containing the data that should be checked.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &var, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger) const override;
public:
/**
@@ -289,27 +289,33 @@ private:
*/
const std::map<std::string, Ordinal> values;
+ /**
+ * Private constructor of the EnumType class used to create a new EnumType
+ * instance from a previously created name to value map. The parameters are
+ * not checked for validity.
+ *
+ * @param mgr is the underlying Manager instance.
+ * @param name is the name of the EnumType instance. Should be a valid
+ * identifier.
+ * @param values is a vector containing the enumeration type constants.
+ */
+ EnumType(Manager &mgr, std::string name, Handle<Typesystem> system,
+ std::map<std::string, Ordinal> values)
+ : Type(mgr, std::move(name), system, false), values(std::move(values))
+ {
+ }
+
protected:
/**
* Converts the given variant to the corresponding enum type representation.
* The variant may either be a magic string containing the name of an
* enumeration type or an integer.
*
- * @param var is a variant containing the data that should be checked.
+ * @param data is a variant containing the data that should be checked.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &var, Logger &logger) const override;
-
- /**
- * Protected constructor of the EnumType class used to create a new EnumType
- * instance from a previously created name to value map.
- */
- EnumType(Manager &mgr, std::string name, Handle<Typesystem> system,
- std::map<std::string, Ordinal> values)
- : Type(mgr, std::move(name), system, false), values(std::move(values))
- {
- }
+ bool doBuild(Variant &data, Logger &logger) const override;
public:
/**
@@ -318,6 +324,7 @@ public:
* @param mgr is the underlying Manager instance.
* @param name is the name of the EnumType instance. Should be a valid
* identifier.
+ * @param system is a reference to the parent Typesystem instance.
* @param values is a vector containing the enumeration type constants.
* The constants are checked for validity (must be a valid identifier) and
* uniqueness (each value must exist exactly once).
@@ -357,7 +364,7 @@ private:
/**
* Reference to the actual type of the attribute.
*/
- Owned<Type> type;
+ const Owned<Type> type;
public:
/**
@@ -377,12 +384,13 @@ public:
* @param type holds a reference to the type descriptor holding the type
* of the attribute.
* @param name is the name of the Attribute. Should be a valid identifier.
- * @param defaultValue is the default value of the attribute
+ * @param defaultValue is the default value of the attribute and must have
+ * been passed through the build of the specified type.
* @param optional should be set to true if the if the default value should
* be used.
*/
Attribute(Manager &mgr, std::string name, Handle<Type> type,
- Variant defaultValue, bool optional)
+ Variant defaultValue, bool optional = true)
: Node(mgr, std::move(name)),
type(acquire(type)),
defaultValue(defaultValue),
@@ -418,60 +426,197 @@ public:
* The StructType class represents a user defined structure.
*/
class StructType : public Type {
-protected:
+private:
/**
- * TODO: DOC
+ * Reference to the parent structure type (or nullptr if the struct type is
+ * not derived from any other struct type).
*/
- bool doBuild(Variant &var, Logger &logger) const override
- {
- // If we already have an array, we just check that.
- if (var.isArray()) {
- auto arr = var.asArray();
- for (size_t a = 0; a < attributes.size(); a++) {
- if (!attributes[a]->getType()->build(arr[a], logger)) {
- return false;
- }
- }
- return true;
- }
- // Otherwise we expect a map.
- if (!var.isMap()) {
- throw LoggableException("Expected map!");
- }
- auto &map = var.asMap();
- // We transform the map into an array with the correct values at the
- // correct places.
- Variant::arrayType vec;
- for (auto &a : attributes) {
- auto it = map.find(a->getName());
- // we use the default if nothing is set.
- if (it == map.end() || !a->getType()->build(it->second, logger)) {
- logger.note(std::string("Using default value for ") +
- a->getName());
- vec.push_back(a->defaultValue);
- } else {
- vec.push_back(it->second);
- }
- }
- var = Variant(vec);
- return true;
- }
+ const Owned<StructType> parent;
-public:
+ /**
+ * Vector containing references to all attribute descriptors.
+ */
const NodeVector<Attribute> attributes;
+ /**
+ * Map storing the attribute names.
+ */
+ const std::map<std::string, size_t> attributeNames;
+
+ /**
+ * Resolves an attribute key string of the form "#idx" to the corresponding
+ * attribute index.
+ *
+ * @param key is the key to be parsed.
+ * @param val is the variable in which the result should be stored.
+ * @return true if the operation was successful, false otherwise.
+ */
+ bool resolveIndexKey(const std::string &key, size_t &idx) const;
+
+ /**
+ * Resolves an attribute key strin of the form "key" to the corresponding
+ * attribute index.
+ *
+ * @param key is the key to be parsed.
+ * @param val is the variable in which the result should be stored.
+ * @return true if the operation was successful, false otherwise.
+ */
+ bool resolveIdentifierKey(const std::string &key, size_t &idx) const;
+
+ /**
+ * Resolves the given attribute key to the corresponding array index.
+ *
+ * @param key is the key to be parsed.
+ * @param val is the variable in which the result should be stored.
+ * @return true if the operation was successful, false otherwise.
+ */
+ bool resolveKey(const std::string &key, size_t &idx) const;
+
+ /**
+ * Inserts default values into unset attribute slots. Loggs errors if a
+ * attribute that was not explicitly set has no default value associated to
+ * it.
+ *
+ * @param data is a variant with array type that should be updated.
+ * @param set indicating which array slots that have been set explicitly.
+ * @param logger used to which error messages and warnings are logged.
+ * @return true if the operation is successful, false otherwise.
+ */
+ bool insertDefaults(Variant &data, const std::vector<bool> &set,
+ Logger &logger) const;
+
+ /**
+ * Checks an array for validity and if possible updates its content to match
+ * the types of the structure type.
+ *
+ * @param data is the variant to be checked.
+ * @param logger used to which error messages and warnings are logged.
+ * @param trim if true, longer arrays are accepted and trimmed to the number
+ * of attributes (as needed when casting from a derived type).
+ * @return true if the operation is successful, false otherwise.
+ */
+ bool buildFromArray(Variant &data, Logger &logger, bool trim) const;
+
+ /**
+ * Checks a map and its entries for validity and if possible updates its
+ * content to match the types of the structure type.
+ *
+ * @param data is the variant to be checked.
+ * @param logger used to which error messages and warnings are logged.
+ * @param trim if true, unspecified indices are ignored. This may be needed
+ * when casting from a derived type.
+ * @return true if the operation is successful, false otherwise.
+ */
+ bool buildFromMap(Variant &data, Logger &logger, bool trim) const;
+
+ /**
+ * Checks a map or an array for validity and if possible updates its content
+ * to match the types of the structure type.
+ *
+ * @param data is the variant to be checked.
+ * @param logger used to which error messages and warnings are logged.
+ * @param trim if true, unspecified indices are ignored. This may be needed
+ * when casting from a derived type.
+ * @return true if the operation is successful, false otherwise.
+ */
+ bool buildFromArrayOrMap(Variant &data, Logger &logger, bool trim) const;
+
+ /**
+ * Private constructor of the StructType class, creates a new instance
+ * without performing any validity checks.
+ *
+ * @param mgr is the underlying Manager instance.
+ * @param name is the name of the EnumType instance. Should be a valid
+ * identifier.
+ * @param system is a reference to the parent Typesystem instance.
+ * @param parent is a reference to the StructType this type is derived from,
+ * may be nullptr.
+ * @param attributes is a vector containing the struct type attributes.
+ */
StructType(Manager &mgr, std::string name, Handle<Typesystem> system,
- ManagedVector<Attribute> attributes)
+ Handle<StructType> parent, NodeVector<Attribute> attributes,
+ std::map<std::string, size_t> attributeNames)
: Type(mgr, std::move(name), system, false),
- attributes(this, std::move(attributes))
+ parent(acquire(parent)),
+ attributes(this, std::move(attributes)),
+ attributeNames(std::move(attributeNames))
{
}
- // TODO
- // static StructType createValidated(
- // Manager &mgr, std::string name, Handle<Typesystem> system,
- // ManagedVector<Attribute> attributes);
- Variant create() const override { return Variant{Variant::arrayType{}}; }
+protected:
+ /**
+ * Converts the given variant to the representation of the structure type.
+ * The variant may either be an array containing the values of the
+ * attributes in the correct order or a map containing the names of the
+ * attributes or their position in the for of a hash symbol "#" folowed by
+ * the index of the attribute. The resulting variant is an array containg
+ * the value of each attribute, extended by the default values
+ * in the correct order.
+ *
+ * @param data is a variant containing the data that should be checked.
+ * @param logger is the Logger instance into which errors should be written.
+ * @return true if the conversion was successful, false otherwise.
+ */
+ bool doBuild(Variant &data, Logger &logger) const override;
+
+public:
+ /**
+ * Creates a new instance of the StructType class and checks the given
+ * parameters for validity.
+ *
+ * @param mgr is the underlying Manager instance.
+ * @param name is the name of the EnumType instance. Should be a valid
+ * identifier.
+ * @param system is a reference to the parent Typesystem instance.
+ * @param parent is a reference to the StructType this type is derived from,
+ * may be nullptr.
+ * @param attributes is a vector containing the struct type attributes.
+ * The attributes are checked for validity (their names must be a valid
+ * identifiers) and uniqueness (each value must exist exactly once).
+ * @param logger is the Logger instance into which errors should be written.
+ */
+ static Rooted<StructType> createValidated(Manager &mgr, std::string name,
+ Handle<Typesystem> system,
+ Handle<StructType> parent,
+ NodeVector<Attribute> attributes,
+ Logger &logger);
+
+ /**
+ * Creates a Variant containing a valid representation of a data instance of
+ * this StructType.
+ *
+ * @return a valid, empty data instance of this type.
+ */
+ Variant create() const override;
+
+ /**
+ * Function to return true if the other type either equals this type or this
+ * type is derived from the other type.
+ *
+ * @param other is the other struct type that should be checked.
+ * @return true if the other type instance points at the same instance as
+ * this type or this type is derived from the other type.
+ */
+ bool derivedFrom(Handle<StructType> other) const;
+
+ /**
+ * Casts the given type instance of a derived type to a type instance valid
+ * for this type. This operation is only valid if this type instance is a
+ * parent of the type instance that generated the data.
+ *
+ * @param data is the data that should be cast to this type. The data must
+ * have been built by a derived type of this type instance.
+ * @param logger is the Logger instance to which errors should be logged.
+ */
+ Variant cast(Variant &data, Logger &logger) const;
+
+ /**
+ * Returns a handle pointing at the parent type.
+ *
+ * @return a rooted handle pointing at the parent type or nullptr, if this
+ * struct type has no parent.
+ */
+ Rooted<StructType> getParent() const { return parent; }
};
/**
@@ -492,12 +637,12 @@ protected:
* Makes sure the given variant is an array and its elements match the inner
* type of the Arraqy.
*
- * @param var is a variant containing the array data that should be checked
+ * @param data is a variant containing the array data that should be checked
* and passed to the inner type validation function.
* @param logger is the Logger instance into which errors should be written.
* @return true if the conversion was successful, false otherwise.
*/
- bool doBuild(Variant &var, Logger &logger) const override;
+ bool doBuild(Variant &data, Logger &logger) const override;
public:
/**