/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
import { assert, unreachableCase } from "@fluidframework/core-utils";
import { ValueSchema } from "../core/index.js";
export function allowsValue(schema, nodeValue) {
    if (schema === undefined) {
        return nodeValue === undefined;
    }
    return valueSchemaAllows(schema, nodeValue);
}
export function valueSchemaAllows(schema, nodeValue) {
    switch (schema) {
        case ValueSchema.String:
            return typeof nodeValue === "string";
        case ValueSchema.Number:
            return typeof nodeValue === "number";
        case ValueSchema.Boolean:
            return typeof nodeValue === "boolean";
        case ValueSchema.FluidHandle:
            return isFluidHandle(nodeValue);
        case ValueSchema.Null:
            return nodeValue === null;
        default:
            unreachableCase(schema);
    }
}
// TODO: replace test in FluidSerializer.encodeValue with this.
export function isFluidHandle(value) {
    if (typeof value !== "object" || value === null || !("IFluidHandle" in value)) {
        return false;
    }
    const handle = value.IFluidHandle;
    // Regular Json compatible data can have fields named "IFluidHandle" (especially if field names come from user data).
    // Separate this case from actual Fluid handles by checking for a circular reference: Json data can't have this circular reference so it is a safe way to detect IFluidHandles.
    const isHandle = handle === value;
    // Since the requirement for this reference to be cyclic isn't particularly clear in the interface (typescript can't model that very well)
    // do an extra test.
    // Since json compatible data shouldn't have methods, and IFluidHandle requires one, use that as a redundant check:
    const getMember = value.get;
    if (typeof getMember !== "function") {
        return false;
    }
    return isHandle;
}
export function assertAllowedValue(value) {
    assert(isAllowedValue(value), 0x843 /* invalid value */);
}
export function isAllowedValue(value) {
    switch (typeof value) {
        case "string":
        case "number":
        case "boolean":
            return true;
        case "object":
            return value === null || isFluidHandle(value);
        default:
            return false;
    }
}
//# sourceMappingURL=valueUtilities.js.map