def _build(config_cls, dictionary, validate=False):  # noqa
    """ Builds an instance of ``config_cls`` using ``dictionary``.

    :param type config_cls: The class to use for building
    :param dict dictionary: The dictionary to use for building ``config_cls``
    :param bool validate: Performs validation before building ``config_cls``,
        defaults to False, optional
    :return: An instance of ``config_cls``
    :rtype: object
    """

    if not is_config_type(config_cls):
        raise ValueError(
            f"cannot build {config_cls!r} from {dictionary!r}, "
            f"{config_cls!r} is not a config"
        )

    # perform jsonschema validation on the given dictionary
    # (simplifys dynamic typecasting)
    if validate:
        jsonschema.validate(dictionary, build_schema(config_cls))

    kwargs = {}
    for var in attr.fields(config_cls):
        if not is_config_var(var):
            continue

        entry = var.metadata[CONFIG_KEY]
        arg_key = entry.name if entry.name else var.name
        arg_default = var.default if var.default is not None else None

        if callable(entry.decoder):
            kwargs[var.name] = entry.decoder(dictionary.get(arg_key, arg_default))
            continue

        if is_array_type(entry.type):
            if is_typing_type(entry.type) and len(entry.type.__args__) > 0:
                nested_type = entry.type.__args__[0]
                if is_config_type(nested_type):
                    kwargs[var.name] = [
                        _build(nested_type, item)
                        for item in dictionary.get(arg_key, [])
                    ]
                else:
                    kwargs[var.name] = typecast(entry.type, dictionary.get(arg_key, []))
        elif is_object_type(entry.type):
            item = dictionary.get(arg_key, {})
            if is_typing_type(entry.type) and len(entry.type.__args__) == 2:
                (_, value_type) = entry.type.__args__
                kwargs[var.name] = {
                    key: _build(value_type, value)
                    if is_config_type(value_type)
                    else typecast(value_type, value)
                    for (key, value) in item.items()
                }
            else:
                kwargs[var.name] = typecast(entry.type, item)
        elif is_config_type(entry.type):
            if arg_key not in dictionary:
                # if the default value for a nested config is the nested config class
                # then build the empty state of the nested config
                if is_config_type(arg_default) and entry.type == arg_default:
                    kwargs[var.name] = _build(entry.type, {})
                else:
                    kwargs[var.name] = arg_default
            else:
                kwargs[var.name] = _build(
                    entry.type, dictionary.get(arg_key, arg_default)
                )
        else:
            if arg_key not in dictionary:
                kwargs[var.name] = arg_default
            else:
                kwargs[var.name] = typecast(
                    entry.type, dictionary.get(arg_key, arg_default)
                )

    return config_cls(**kwargs)
Builds an instance of ``config_cls`` using ``dictionary``.

    :param type config_cls: The class to use for building
    :param dict dictionary: The dictionary to use for building ``config_cls``
    :param bool validate: Performs validation before building ``config_cls``,
        defaults to False, optional
    :return: An instance of ``config_cls``
    :rtype: object