import { utf8ByteLength } from "../../request-limits";

const MAXIMUM_SUBJECT_BYTES = 16 * 1024 * 1024;
const MAXIMUM_PATTERN_BYTES = 256 * 1024;
const MAXIMUM_REPLACEMENT_BYTES = 256 * 1024;
const MAXIMUM_NON_STRING_JSON_BYTES = 64 * 1024;
const MAXIMUM_JSON_ESCAPE_EXPANSION = 6;

/**
 * Covers the worst case where every accepted one-byte input character becomes
 * a six-byte JSON Unicode escape, plus a bounded allowance for field names,
 * flags, options and numeric limits.
 */
export const MAXIMUM_PORTABLE_REQUEST_JSON_BYTES =
  MAXIMUM_JSON_ESCAPE_EXPANSION *
    (MAXIMUM_SUBJECT_BYTES +
      MAXIMUM_PATTERN_BYTES +
      MAXIMUM_REPLACEMENT_BYTES) +
  MAXIMUM_NON_STRING_JSON_BYTES;

export function stringifyBoundedJsonRequest(
  value: unknown,
  maximumBytes: number,
  label: string,
): string {
  let encoded: string;
  try {
    encoded = JSON.stringify(value);
  } catch {
    throw new Error(`${label} could not serialize its request.`);
  }
  if (utf8ByteLength(encoded) > maximumBytes) {
    throw new Error(`${label} request exceeds its encoded JSON limit.`);
  }
  return encoded;
}
