/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { assert, fail } from "@fluidframework/core-utils/internal";
import { cleanedPackageVersion as runtimeUtilsCleanedPackageVersion } from "@fluidframework/runtime-utils/internal";
/**
 * A {@link JsonValidator} implementation which performs no validation and accepts all data as valid.
 * @privateRemarks Having this as an option unifies opting out of validation with selection of
 * validators, simplifying code performing validation.
 */
const noopValidator = {
    compile: () => ({ check: (data) => true }),
};
/**
 * A {@link FormatValidator} which does no validation.
 * @alpha
 */
export const FormatValidatorNoOp = toFormatValidator(noopValidator);
/**
 * Type erase a {@link JsonValidator} to a {@link FormatValidator}.
 */
export function toFormatValidator(factory) {
    return factory;
}
/**
 * Un-type-erase the {@link FormatValidator}.
 */
export function extractJsonValidator(input) {
    return input;
}
/**
 * Type erase the more detailed encoded type from a codec.
 */
export function eraseEncodedType(codec) {
    return codec;
}
export class UniqueDependentFormatVersion {
    constructor(child) {
        this.child = child;
    }
    lookup(_parent) {
        return this.child;
    }
}
export class MappedDependentFormatVersion {
    constructor(map) {
        this.map = map;
    }
    lookup(parent) {
        return this.map.get(parent) ?? fail(0xc73 /* Unknown parent version */);
    }
}
export const DependentFormatVersion = {
    fromUnique: (child) => new UniqueDependentFormatVersion(child),
    fromMap: (map) => new MappedDependentFormatVersion(map),
    fromPairs: (pairs) => new MappedDependentFormatVersion(new Map(pairs)),
};
/**
 * Creates a codec family from a registry of codecs.
 */
export function makeCodecFamily(registry) {
    const codecs = new Map();
    for (const [formatVersion, codec] of registry) {
        if (codecs.has(formatVersion)) {
            fail(0xabf /* Duplicate codecs specified. */);
        }
        codecs.set(formatVersion, codec);
    }
    return {
        resolve(formatVersion) {
            const codec = codecs.get(formatVersion);
            assert(codec !== undefined, 0x5e6 /* Requested codec for unsupported format. */);
            return codec;
        },
        getSupportedFormats() {
            return codecs.keys();
        },
    };
}
/**
 * Codec for objects which carry no information.
 */
export const unitCodec = {
    encode: () => 0,
    decode: () => 0,
};
/**
 * Wraps a codec with JSON schema validation for its encoded type.
 * @returns An {@link IJsonCodec} which validates the data it encodes and decodes matches the provided schema.
 * @remarks
 * Eventually all codecs should use the same pattern implemented by VersionDispatchingCodecBuilder, resulting in that having the only use of this API.
 */
export function withSchemaValidation(schema, codec, validator) {
    if (!validator) {
        return codec;
    }
    const compiledFormat = extractJsonValidator(validator).compile(schema);
    return {
        encode: (obj, context) => {
            const encoded = codec.encode(obj, context);
            if (!compiledFormat.check(encoded)) {
                fail(0xac0 /* Encoded data should validate */);
            }
            return encoded;
        },
        decode: (encoded, context) => {
            if (!compiledFormat.check(encoded)) {
                fail(0xac1 /* Data being decoded should validate */);
            }
            return codec.decode(encoded, context);
        },
        encodedSchema: schema,
    };
}
/**
 * Versions of Fluid Framework client packages, usable as a {@link @fluidframework/runtime-definitions#MinimumVersionForCollab}.
 * @remarks
 * Versions with no notable impact may be omitted, and added later if needed.
 *
 * @privateRemarks
 * Each entry should document:
 * - The user-facing impact of opting into it (e.g. encoding efficiency improvements).
 * - Any new data formats introduced in that version.
 * - Whether those features/formats are enabled by default or require {@link MinimumVersionForCollab | minVersionForCollab} to be set accordingly.
 * @alpha
 */
export const FluidClientVersion = {
    /**
     * Fluid Framework Client 2.0 and newer.
     */
    v2_0: "2.0.0",
    /**
     * Fluid Framework Client 2.43 and newer.
     * @remarks
     * New formats introduced in 2.43:
     * - SchemaFormatVersion.v2 - written when minVersionForCollab \>= 2.43
     * - MessageFormatVersion.v4 - written when minVersionForCollab \>= 2.43
     * - EditManagerFormatVersion.v4 - written when minVersionForCollab \>= 2.43
     * - sequence-field/formatV3 - written when minVersionForCollab \>= 2.43
     */
    v2_43: "2.43.0",
    /**
     * Fluid Framework Client 2.52 and newer.
     * @remarks
     * New formats introduced in 2.52:
     * - DetachedFieldIndexFormatVersion.v2 - written when minVersionForCollab \>= 2.52
     */
    v2_52: "2.52.0",
    /**
     * Fluid Framework Client 2.73 and newer.
     * @remarks
     * New formats introduced in 2.73:
     * - FieldBatchFormatVersion.v2 - written when minVersionForCollab \>= 2.73
     */
    v2_73: "2.73.0",
    /**
     * Fluid Framework Client 2.74 and newer.
     * @remarks
     * New formats introduced in 2.74:
     * - SharedTreeSummaryFormatVersion.v2 - written by default
     * - DetachedFieldIndexSummaryFormatVersion.v2 - written by default
     * - SchemaSummaryFormatVersion.v2 - written by default
     * - EditManagerSummaryFormatVersion.v2 - written by default
     * - ForestSummaryFormatVersion.v2 - written by default
     * - ForestFormatVersion.v2 - written when minVersionForCollab \>= 2.74
     * - ForestSummaryFormatVersion.v3 - written when minVersionForCollab \>= 2.74
     */
    v2_74: "2.74.0",
    /**
     * Fluid Framework Client 2.80 and newer.
     * @remarks
     * New formats introduced in 2.80:
     * - MessageFormatVersion.v6 - written when minVersionForCollab \>= 2.80
     * - EditManagerFormatVersion.v6 - written when minVersionForCollab \>= 2.80
     * - SharedTreeChangeFormatVersion.v5 - written when minVersionForCollab \>= 2.80
     * - ModularChangeFormatVersion.v5 - written when minVersionForCollab \>= 2.80
     */
    v2_80: "2.80.0",
};
/**
 * An up to date version which includes all stable features.
 * @remarks
 * Use for cases when data is not persisted and thus would only ever be read by the the same version of the code which read this value.
 *
 * The pkgVersion from this package (tree) can not be used here as it is not guaranteed to be a valid MinimumVersionForCollab
 * and would also unexpectedly disable features in prereleases and on CI if it didn't fail validation.
 * See {@link @fluidframework/runtime-utils/internal#cleanedPackageVersion} for more details on why cleanedPackageVersion is preferred over pkgVersion.
 *
 * @privateRemarks
 * It is safe to use CleanedPackageVersion from runtime-utils here since features are enabled in minor versions,
 * and this package (tree) depends on runtime-utils with a `~` semver range
 * ensuring that the version of runtime-utils this was imported from will match the version of this (tree) package at least up to the minor version.
 * Reusing this from runtime-utils avoids duplicating the cleanup logic here as well as the cost or recomputing it.
 * If in the future for some reason this becomes not okay, runtime-utils could instead export a function that performs that cleanup logic which could be reused here.
 */
export const currentVersion = runtimeUtilsCleanedPackageVersion;
export function jsonableCodecTree(tree) {
    return {
        name: tree.name,
        version: tree.version ?? "null",
        children: tree.children?.map(jsonableCodecTree),
    };
}
//# sourceMappingURL=codec.js.map