UNPKG

@struktoai/mirage-core

Version:

A Unified Virtual Filesystem For AI Agents

91 lines • 3.52 kB
// ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // ========= Copyright 2026 @ Strukto.AI All Rights Reserved. ========= import { MODE_BASES, MODE_CHARS } from "./constants.js"; /** A handle that only reads, as an open with no flags asks for. */ export const READ = Object.freeze({ readable: true, writable: false, truncate: false, append: false, create: false, exclusive: false, binary: true, }); /** * What open(2) flags say about a handle, in the mode vocabulary. The flag * numbers are the host's (`fs.constants` under node, Emscripten's own), so * they come with the flags. Mirrors Python's `open_mode`. */ export function openMode(flags, bits) { const access = flags & (bits.O_WRONLY | bits.O_RDWR); const writable = access === bits.O_WRONLY || access === bits.O_RDWR; const create = (flags & bits.O_CREAT) !== 0; return { readable: access === 0 || access === bits.O_RDWR, writable, truncate: writable && (flags & bits.O_TRUNC) !== 0, append: (flags & bits.O_APPEND) !== 0, create, exclusive: create && (flags & bits.O_EXCL) !== 0, binary: true, }; } /** * Read an fopen-style mode string into its facts, validating it. * * The rule is CPython's: one base, at most one each of `+`, `b`, `t`, * and never `b` together with `t`. A guest that opens in C's dialect * (QuickJS's std.open: fopen reads `rr` as `r` and spells exclusive * creation `wx`) reads its own mode and builds these facts itself. * * Args: * mode: the mode as the caller spelled it (`r`, `w+b`, `a`, `x`, ...). * * Throws: * Error: the mode does not parse, in CPython's own wording. */ export function parseMode(mode) { const count = (char) => mode.split(char).length - 1; let bases = ''; for (const char of 'rwax') if (mode.includes(char)) bases += char; let duplicated = false; for (const char of MODE_CHARS) if (count(char) > 1) duplicated = true; let invalid = false; for (const char of mode) if (!MODE_CHARS.includes(char)) invalid = true; if (invalid || duplicated) throw new Error(`invalid mode: '${mode}'`); if (mode.includes('b') && mode.includes('t')) throw new Error("can't have text and binary mode at once"); if (!bases) throw new Error('Must have exactly one of create/read/write/append mode and at most one plus'); if (!MODE_BASES.includes(bases)) throw new Error('must have exactly one of create/read/write/append mode'); const plus = mode.includes('+'); return { readable: mode.includes('r') || plus, writable: !mode.includes('r') || plus, truncate: mode.includes('w'), append: mode.includes('a'), create: /[wax]/.test(mode), exclusive: mode.includes('x'), binary: mode.includes('b'), }; } //# sourceMappingURL=mode.js.map