configy.Read

Utilities to fill a struct representing the configuration with the content of a YAML document.

The main function of this module is parseConfig. Convenience functions parseConfigString and parseConfigFile are also available.

The type parameter to those three functions must be a struct and is used to drive the processing of the YAML node. When an error is encountered, an Exception will be thrown, with a descriptive message. The rules by which the struct is filled are designed to be as intuitive as possible, and are described below.

Public Imports

configy.Attributes
public import configy.Attributes;
Undocumented in source.

Members

Classes

ConfigException (from configy.Exceptions)
class ConfigException via public import configy.Exceptions : ConfigException;

Base exception type thrown by the config parser

Enums

StrictMode
enum StrictMode

The behavior to have when encountering a field in YAML not present in the config definition.

Functions

parseConfig
T parseConfig(CLIArgs cmdln, Node node, StrictMode strict)

Process the content of the YAML document described by node into an instance of the struct T.

parseConfigFile
T parseConfigFile(CLIArgs cmdln, StrictMode strict)

Parses the config file or string and returns a Config instance.

parseConfigFileSimple
Nullable!T parseConfigFileSimple(string path, StrictMode strict)
Nullable!T parseConfigFileSimple(CLIArgs args, StrictMode strict)

Attempt to read and process the config file at path, print any error

parseConfigString
T parseConfigString(string data, string path, StrictMode strict)

Parses the config file or string and returns a Config instance.

parseField
FR.Type parseField(Node node, string path, FR.Type defaultValue, Context ctx)

Parse a field, trying to match up the compile-time expectation with the run time value of the Node (nodeID).

Structs

CLIArgs
struct CLIArgs

Command-line arguments

Context
struct Context

Used to pass around configuration

Detailed Description

Optional Fields

One of the major convenience offered by this utility is its handling of optional fields. A field is detected as optional if it has an initializer that is different from its type init value, for example string field = "Something"; is an optional field, but int count = 0; is not. To mark a field as optional even with its default value, use the Optional UDA: @Optional int count = 0;.

Converter: Because config structs may contain complex types such as a Phobos type, a user-defined Amount, or Vibe.d's URL, one may need to apply a converter to a struct's field. Converters are functions that take a YAML Node as argument and return a type that is implicitly convertible to the field type (usually just the field type). They offer the most power to users, as they can inspect the YAML structure, but should be used as a last resort.

Composite Types

Processing starts from a struct at the top level, and recurse into every fields individually. If a field is itself a struct, the filler will attempt the following, in order: - If the field has no value and is not optional, an Exception will be thrown with an error message detailing where the issue happened. - If the field has no value and is optional, the default value will be used. - If the field has a value, the filler will first check for a converter and use it if present. - If the type has a static method named fromString whose sole argument is a string, it will be used. - If the type has a constructor whose sole argument is a string, it will be used; - Finally, the filler will attempt to deserialize all struct members one by one and pass them to the default constructor, if there is any. - If none of the above succeeded, a static assert will trigger.

Alias this

If a struct contains an alias this, the field that is aliased will be ignored, instead the config parser will parse nested fields as if they were part of the enclosing structure. This allow to re-use a single struct in multiple place without having to resort to a mixin template. Having an initializer will make all fields in the aliased struct optional. The aliased field cannot have attributes other than @Optional, which will then apply to all fields it exposes.

Duration parsing

If the config field is of type core.time.Duration, special parsing rules will apply. There are two possible forms in which a Duration field may be expressed. In the first form, the YAML node should be a mapping, and it will be checked for fields matching the supported units in core.time: weeks, days, hours, minutes, seconds, msecs, usecs, hnsecs, nsecs. Strict parsing option will be respected. The values of the fields will then be added together, so the following YAML usages are equivalent:

// sleepFor:
//   hours: 8
//   minutes: 30

and:

// sleepFor:
//   minutes: 510

Provided that the definition of the field is:

public Duration sleepFor;

In the second form, the field should have a suffix composed of an underscore ('_'), followed by a unit name as defined in core.time. This can be either the field name directly, or a name override. The latter is recommended to avoid confusion when using the field in code. In this form, the YAML node is expected to be a scalar. So the previous example, using this form, would be expressed as:

sleepFor_minutes: 510

and the field definition should be one of those two:

public @Name("sleepFor_minutes") Duration sleepFor; /// Prefer this
public Duration sleepFor_minutes; /// This works too

Those forms are mutually exclusive, so a field with a unit suffix will error out if a mapping is used. This prevents surprises and ensures that the error message, if any, is consistent accross user input.

To disable or change this behavior, one may use a Converter instead.

Strict Parsing

When strict parsing is enabled, the config filler will also validate that the YAML nodes do not contains entry which are not present in the mapping (struct) being processed. This can be useful to catch typos or outdated configuration options.

Post Validation

Some configuration will require validation accross multiple sections. For example, two sections may be mutually exclusive as a whole, or may have fields which are mutually exclusive with another section's field(s). This kind of dependence is hard to account for declaratively, and does not affect parsing. For this reason, the preferred way to handle those cases is to define a validate member method on the affected config struct(s), which will be called once parsing for that mapping is completed. If an error is detected, this method should throw an Exception.

Enabled or disabled field

While most complex logic validation should be handled post-parsing, some section may be optional by default, but if provided, will have required fields. To support this use case, if a field with the name enabled is present in a struct, the parser will first process it. If it is false, the parser will not attempt to process the struct further, and the other fields will have their default value. Likewise, if a field named disabled exists, the struct will not be processed if it is set to true.

Meta

License

MIT License. See LICENSE for details.