"use strict";
/*!
 * Copyright (c) Microsoft Corporation and contributors. All rights reserved.
 * Licensed under the MIT License.
 */
Object.defineProperty(exports, "__esModule", { value: true });
exports.isAllowedValue = exports.assertAllowedValue = exports.isFluidHandle = exports.valueSchemaAllows = exports.allowsValue = void 0;
const core_utils_1 = require("@fluidframework/core-utils");
const core_1 = require("../core");
function allowsValue(schema, nodeValue) {
    if (schema === undefined) {
        return nodeValue === undefined;
    }
    return valueSchemaAllows(schema, nodeValue);
}
exports.allowsValue = allowsValue;
function valueSchemaAllows(schema, nodeValue) {
    switch (schema) {
        case core_1.ValueSchema.String:
            return typeof nodeValue === "string";
        case core_1.ValueSchema.Number:
            return typeof nodeValue === "number";
        case core_1.ValueSchema.Boolean:
            return typeof nodeValue === "boolean";
        case core_1.ValueSchema.FluidHandle:
            return isFluidHandle(nodeValue);
        case core_1.ValueSchema.Null:
            return nodeValue === null;
        default:
            (0, core_utils_1.unreachableCase)(schema);
    }
}
exports.valueSchemaAllows = valueSchemaAllows;
// TODO: replace test in FluidSerializer.encodeValue with this.
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;
}
exports.isFluidHandle = isFluidHandle;
function assertAllowedValue(value) {
    (0, core_utils_1.assert)(isAllowedValue(value), "invalid value");
}
exports.assertAllowedValue = assertAllowedValue;
function isAllowedValue(value) {
    switch (typeof value) {
        case "string":
        case "number":
        case "boolean":
            return true;
        case "object":
            return value === null || isFluidHandle(value);
        default:
            return false;
    }
}
exports.isAllowedValue = isAllowedValue;
//# sourceMappingURL=valueUtilities.js.map