Parses the options.

@param {number|string|object|undefined} options - An option object to parse.
@param {number} defaultVersion - The default version to use if the version option was omitted.
@returns {object} Parsed value.
function parseOptions(options, defaultVersion) {
    let version = null
    let range = null
    let ignores = []

    if (typeof options === "number") {
        version = VERSION_MAP.get(options)
    } else if (typeof options === "string") {
        version = options
    } else if (typeof options === "object") {
        version =
            typeof options.version === "number"
                ? VERSION_MAP.get(options.version)
                : options.version

        ignores = options.ignores || []
    }

    range = semver.validRange(version ? `>=${version}` : defaultVersion)
    if (!version) {
        version = defaultVersion
    }

    return Object.freeze({
        version,
        features: Object.freeze(
            OPTIONS.reduce((retv, key) => {
                const feature = FEATURES[key]

                if (isIgnored(key, ignores)) {
                    retv[key] = Object.freeze({
                        name: feature.name,
                        singular: Boolean(feature.singular),
                        supported: true,
                        supportedInStrict: true,
                    })
                } else if (typeof feature.node === "string") {
                    retv[key] = Object.freeze({
                        name: feature.name,
                        singular: Boolean(feature.singular),
                        supported: !semver.intersects(
                            range,
                            `<${feature.node}`
                        ),
                        supportedInStrict: !semver.intersects(
                            range,
                            `<${feature.node}`
                        ),
                    })
                } else {
                    retv[key] = Object.freeze({
                        name: feature.name,
                        singular: Boolean(feature.singular),
                        supported:
                            feature.node != null &&
                            feature.node.sloppy != null &&
                            !semver.intersects(
                                range,
                                `<${feature.node.sloppy}`
                            ),
                        supportedInStrict:
                            feature.node != null &&
                            feature.node.strict != null &&
                            !semver.intersects(
                                range,
                                `<${feature.node.strict}`
                            ),
                    })
                }

                return retv
            }, Object.create(null))
        ),
    })
}