feat(logic): add array sizing-policy helpers
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,54 @@
|
|||||||
|
// Pure helpers for array-valued local state: parse the declared initial value
|
||||||
|
// and enforce the declared sizing policy (dynamic / capped / fixed). Shared by
|
||||||
|
// localstate.ts (write path) and logic.ts (node handlers + migration).
|
||||||
|
|
||||||
|
import type { StateVar } from './types';
|
||||||
|
|
||||||
|
export type ArrVal = number | ArrVal[];
|
||||||
|
export const ARRAY_MAX = 1_000_000;
|
||||||
|
|
||||||
|
// zeroFill builds a length-n array of zeros (flat; fixed nested init must come
|
||||||
|
// from an explicit `initial` literal).
|
||||||
|
function zeroFill(n: number): ArrVal[] {
|
||||||
|
return new Array(Math.max(0, n)).fill(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// parseInitialArray returns the starting contents of an array local.
|
||||||
|
export function parseInitialArray(sv: StateVar): ArrVal[] {
|
||||||
|
const cap = sv.capacity ?? 0;
|
||||||
|
const raw = (sv.initial ?? '').trim();
|
||||||
|
let parsed: ArrVal[] | null = null;
|
||||||
|
if (raw) {
|
||||||
|
try {
|
||||||
|
const j = JSON.parse(raw);
|
||||||
|
if (Array.isArray(j)) parsed = j as ArrVal[];
|
||||||
|
} catch { parsed = null; }
|
||||||
|
}
|
||||||
|
if (sv.sizing === 'fixed') {
|
||||||
|
if (!parsed) return zeroFill(cap);
|
||||||
|
// truncate / zero-pad to capacity
|
||||||
|
const out = parsed.slice(0, cap);
|
||||||
|
while (out.length < cap) out.push(0);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
return parsed ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// applySizing returns arr clamped to the declared policy.
|
||||||
|
// dynamic → unchanged (but globally capped at ARRAY_MAX, dropping oldest)
|
||||||
|
// capped → keep at most capacity elements, dropping oldest (ring/FIFO)
|
||||||
|
// fixed → exactly capacity elements (truncate / zero-pad); never grow/shrink
|
||||||
|
export function applySizing(arr: ArrVal[], sv: StateVar): ArrVal[] {
|
||||||
|
const cap = sv.capacity ?? 0;
|
||||||
|
switch (sv.sizing) {
|
||||||
|
case 'fixed': {
|
||||||
|
const out = arr.slice(0, cap);
|
||||||
|
while (out.length < cap) out.push(0);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
case 'capped':
|
||||||
|
return arr.length > cap ? arr.slice(arr.length - cap) : arr;
|
||||||
|
default:
|
||||||
|
return arr.length > ARRAY_MAX ? arr.slice(arr.length - ARRAY_MAX) : arr;
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user