monty-types
The shared boundary types exchanged between hosts and the sandbox: values, exceptions, resource limits and host-call payloads. Host-side code depends on this crate rather than on the interpreter.
pub mod args;
ToArgs / ToMontyObject — projection of typed args structs into
the (positional, keyword) MontyObject pairs host callbacks consume.
The #[derive(ToArgs)] macro in monty-macros emits impls of these
traits via crate::args::… paths, which resolve in this crate.
pub trait ToArgs {
fn to_args(self) -> (Vec<MontyObject>, Vec<(MontyObject, MontyObject)>);
}
Projects a typed args struct into the (positional, keyword) MontyObject
pair host callbacks expect. Consumes self to avoid cloning owned fields.
Inverse of monty’s internal FromArgs (ArgValues → struct); ToArgs
is struct → host-facing (args, kwargs). Driven by
os::OsFunctionCall::to_args for the monty-python / monty-js bindings.
pub trait ToMontyObject {
fn into_monty_object(self) -> MontyObject;
}
Consume self into a MontyObject.
MontyObject is the host-facing, heap-free representation. Implementers
just shape themselves into the most natural MontyObject variant —
String → MontyObject::String, Vec<u8> → MontyObject::Bytes, etc.
pub mod format;
Pure CPython-compatible formatting helpers shared by the boundary types:
string/bytes repr() escaping, shortest-round-trip float rendering, and
timezone-offset timedelta reprs.
pub fn string_repr_fmt(s: &str, f: &mut impl Write) -> fmt::Result;
Writes a Python repr() string for a given string slice to a formatter.
Quote choice matches CPython: single quotes by default, switching to double
quotes only when the string contains a ' but no " (so the quote needn’t
be escaped). Backslash, the active quote, and \n/\t/\r use the short
escapes; any other non-printable character is escaped numerically
(\xNN/\uNNNN/\UNNNNNNNN), e.g. repr('\x00') == "'\\x00'" and
repr('\xa0') == "'\\xa0'".
“Non-printable” matches CPython’s str.isprintable (see
repr_needs_escape): Unicode categories C* and Z*, except the ASCII
space. Category data comes from unicode-general-category, whose Unicode
version may differ slightly from CPython’s, affecting only recently
(re)assigned code points.
pub struct StringRepr<'a>(pub &'a str);
Formatter for a Python repr() string.
Implements: Debug, Display.
pub fn bytes_repr_fmt(bytes: &[u8], f: &mut impl Write) -> fmt::Result;
Writes a CPython-compatible repr string for bytes to a formatter.
Format: b'...' or b"..." depending on content.
- Uses single quotes by default
- Switches to double quotes if bytes contain
'but not" - Escapes:
\\,\t,\n,\r,\xNNfor non-printable bytes
pub fn bytes_repr(bytes: &[u8]) -> String;
Returns a CPython-compatible repr string for bytes.
Convenience wrapper around bytes_repr_fmt that returns an owned String.
pub struct FormatFloat(pub f64);
A Display adapter that writes a float exactly as CPython’s
repr()/str() (identical for floats in Python 3): the shortest decimal
string that round-trips, switching to scientific notation when the base-10
exponent is < -4 or >= 16, and always keeping at least one fractional
digit (1.0, never 1) — 1e16 → "1e+16", 1234.5 → "1234.5",
inf/nan lowercased.
This is the default rendering for a bare f"{x}", str(x), repr(x) and
floats inside container reprs — not the format mini-language (that’s
format_float_g et al, in monty). Rust can’t do this directly: its f64 Display
never uses scientific notation (1e16 prints as 10000000000000000) and
renders NaN as "NaN".
As a Display adapter it writes straight to the caller’s sink with no
heap allocation: it borrows Rust’s shortest-digits guarantee via {:e}
into a small stack buffer (an f64 {:e} is ASCII and ≤ 24 bytes) and
re-lays-out those digits per CPython’s rules.
Implements: Display.
pub fn utf8_error_reason(first_bad_byte: u8, error_len: Option<usize>) -> &'static str;
Classifies an invalid-UTF-8 error into CPython’s reason wording, from the
first unexpected byte and Utf8Error::error_len().
error_len == None means the input ended mid-sequence (unexpected end of data); otherwise a byte that is a legal multi-byte lead (0xC2–0xF4) was
followed by an invalid continuation, and anything else (stray
continuation bytes, the overlong leads 0xC0/0xC1, 0xF5–0xFF) is an
invalid start byte. Public (re-exported at the crate root) so monty-fs
produces identical wording for text-mode file reads.
pub fn format_offset_timedelta_repr(offset_seconds: i32) -> String;
Formats the canonical datetime.timedelta(...) repr for a fixed timezone
offset in seconds, normalized like Python’s timedelta (days may be
negative, seconds in 0..86400) — e.g. -18000 →
datetime.timedelta(days=-1, seconds=68400). Used by the
datetime.timezone reprs of MontyObject.
pub const MONTY_VERSION: &str = "0.0.21";
The monty version this build was compiled as.
pub enum BuiltinsFunctions {
Abs,
All,
Any,
Bin,
Chr,
Divmod,
Enumerate,
Filter,
Getattr,
Hasattr,
Hash,
Hex,
Id,
Isinstance,
Len,
Map,
Max,
Min,
Next,
Oct,
Open,
Ord,
Pow,
Print,
Repr,
Reversed,
Round,
Setattr,
Sorted,
Sum,
Type,
Zip,
/// `object.__setattr__(obj, name, value)` — the write that bypasses a
/// class's attribute hooks, reached only through `object`. Its name is not
/// an identifier, so it can never resolve as a bare global.
///
/// The first variant whose name is not its lowercased identifier, so it
/// needs both renames: serde and strum each carry the name across a
/// different boundary (JSON vs. `Display`/`FromStr`) and must agree.
ObjectSetattr,
}
Enumerates every interpreter-native Python builtin function.
Listed alphabetically per https://docs.python.org/3/library/functions.html Commented-out variants are not yet implemented.
Note: Type constructors are handled by the Type enum, not here.
Uses strum derives for automatic Display, FromStr, and IntoStaticStr implementations.
All variants serialize to lowercase (e.g., Print -> “print”).
pub const fn from_repr(discriminant: u8) -> Option<BuiltinsFunctions>
Try to create Self from the raw representation
Implements: Clone, Copy, Debug, Deserialize<'de>, Display, Eq, From<&'_derivative_strum BuiltinsFunctions>, From<BuiltinsFunctions>, FromStr, Hash, PartialEq, Serialize, StructuralPartialEq, TryFrom<&str>.
pub struct CodeLoc {
/// Line number (1-based).
pub line: u32,
/// Column number (1-based), counted in characters (not bytes).
pub column: u32,
}
A line and column position in source code.
Uses 1-based indexing for both line and column to match Python’s conventions.
u32 matches ruff_text_size::TextSize, which underpins all source ranges
returned by the parser, so conversions between the two are zero-cost.
pub fn new(line: u32, column: u32) -> Self
Creates a new CodeLoc from 0-based values.
Lines and columns numbers are 1-indexed for display, hence + 1.
Saturates at u32::MAX rather than panicking — overflow here is
already unreachable for any source ruff will accept (it caps source
size at 4 GiB), and saturation keeps the parser panic-free even if
that ever changes.
Implements: Clone, Copy, Debug, Default, Deserialize<'de>, Eq, Hash, PartialEq, Serialize, StructuralPartialEq.
pub enum ExcData {
/// No structured payload — every exception type without a variant below.
None,
/// `UnicodeDecodeError` / `UnicodeEncodeError` constructor fields.
/// Boxed to keep the common `None` case (and every exception embedding
/// this enum) small.
Unicode(Box<UnicodeErrorData>),
/// `json.JSONDecodeError` attribute fields. Boxed like
/// `ExcData::Unicode` to keep the enum small.
Json(Box<JsonErrorData>),
}
Structured payload attached to exception types whose CPython counterparts
carry more than a message. Currently unicode and json decode errors have
one; the enum leaves room for future variants (e.g. OSError’s
errno/filename) without another field on every exception.
pub fn unicode(&self) -> Option<&UnicodeErrorData>
The unicode-error fields, if this is ExcData::Unicode.
pub fn json(&self) -> Option<&JsonErrorData>
The json-error fields, if this is ExcData::Json.
Implements: Clone, Debug, Default, Deserialize<'de>, Hash, PartialEq, Serialize, StructuralPartialEq.
pub enum ExcType {
/// primary exception class - matches any exception in isinstance checks.
///
/// Also the `Default` — required so `Type` (which embeds an `ExcType` in
/// its `Exception` variant) can derive `strum::EnumIter`.
Exception,
/// System exit exceptions
BaseException,
SystemExit,
KeyboardInterrupt,
/// Intermediate class for arithmetic errors.
ArithmeticError,
/// Subclass of ArithmeticError.
OverflowError,
/// Subclass of ArithmeticError.
ZeroDivisionError,
/// Intermediate class for lookup errors.
LookupError,
/// Subclass of LookupError.
IndexError,
/// Subclass of LookupError.
KeyError,
/// Intermediate class for runtime errors.
RuntimeError,
/// Subclass of RuntimeError.
NotImplementedError,
/// Subclass of RuntimeError.
RecursionError,
AttributeError,
/// Subclass of AttributeError (from dataclasses module).
FrozenInstanceError,
NameError,
/// Subclass of NameError - for accessing local variable before assignment.
UnboundLocalError,
ValueError,
/// Subclass of ValueError - for encoding/decoding errors.
UnicodeDecodeError,
/// Subclass of ValueError - for encoding errors (e.g. `str.encode('ascii')`
/// on a string containing non-ASCII characters).
UnicodeEncodeError,
/// Subclass of ValueError for invalid JSON syntax in `json.loads()`.
JsonDecodeError,
/// Import-related errors (module not found, name not in module).
ImportError,
/// Subclass of ImportError - for when a module cannot be found.
ModuleNotFoundError,
/// OS-related errors (file not found, permission denied, etc.)
OSError,
/// Subclass of OSError - for when a file or directory cannot be found.
FileNotFoundError,
/// Subclass of OSError - for when a file already exists.
FileExistsError,
/// Subclass of OSError - for when a path is a directory but a file was expected.
IsADirectoryError,
/// Subclass of OSError - for when a path is not a directory but one was expected.
NotADirectoryError,
/// Subclass of OSError - for when an operation is not permitted (e.g., writing
/// to a read-only mount, or attempting to access a path outside a mounted directory).
PermissionError,
/// `io.UnsupportedOperation` - raised by file objects when a requested
/// operation isn't allowed by the open mode (e.g. `read()` on `'w'`).
///
/// In CPython this inherits from both `OSError` and `ValueError`. Monty's
/// `ExcType` enum models single parents, but `Self::is_subclass_of`
/// matches `UnsupportedOperation` against both `OSError` and `ValueError`
/// so `except ValueError:` and `except OSError:` both catch it as in
/// CPython.
UnsupportedOperation,
/// Subclass of OSError since Python 3.3 (PEP 3151).
TimeoutError,
AssertionError,
MemoryError,
StopIteration,
SyntaxError,
TypeError,
/// `re.PatternError` - raised for invalid regex patterns or unsupported regex features.
///
/// # Behavior Note
///
/// Limited to monty's exception type, `PatternError` does not provide `pattern`, `pos`,
/// `lineno` and `colno` attributes.
///
/// As per CPython's implementation, it would be hard to convert `fancy-regex`'s error
/// representations into the required attributes.
RePatternError,
/// `binascii.Error` - raised by the `base64` codecs for malformed input.
///
/// A `ValueError` subclass in CPython, so `except ValueError:` catches it.
/// Monty's `binascii` module exposes this class and nothing else.
BinasciiError,
}
Python exception types supported by the interpreter.
Uses strum derives for automatic Display, FromStr, and Into<&'static str> implementations.
The string representation matches the variant name exactly (e.g., ValueError -> “ValueError”),
except where a serialize attribute gives a dotted name to disambiguate a stdlib subclass from
its builtin parent (binascii.Error from ValueError, say).
ExcType::VARIANTS is the canonical list of those names, and the host bridges mirror it:
PYTHON_EXC_NAMES in crates/monty-js/ts/errors.ts and the ExcType literal in
pydantic_monty/__init__.py. Both are hand-written, so monty-proto’s exc_type_bridges test
reads them and pins them here — adding a variant without wiring the bridges fails that test.
pub fn is_subclass_of(self, handler_type: Self) -> bool
Checks if this exception type is a subclass of another exception type.
Implements Python’s exception hierarchy for try/except matching:
Exceptionis the base class for all standard exceptionsLookupErroris the base forKeyErrorandIndexErrorArithmeticErroris the base forZeroDivisionErrorandOverflowErrorRuntimeErroris the base forRecursionErrorandNotImplementedError
Returns true if self would be caught by except handler_type:.
Implements: Clone, Copy, Debug, Default, Deserialize<'de>, Display, Eq, From<&'_derivative_strum ExcType>, From<ExcType>, FromStr, Hash, PartialEq, Serialize, StructuralPartialEq, TryFrom<&str>, VariantNames.
pub struct JsonErrorData {
/// The bare error message, without the `: line N column M (char K)`
/// suffix the formatted exception message carries.
pub msg: String,
/// The document being parsed, matching CPython's `exc.doc`. `None` when
/// the document exceeds `JsonErrorData::MAX_DOC_LEN` or is not valid
/// UTF-8 (`json.loads` on `bytes` input).
pub doc: Option<String>,
/// Character index of the error in `doc`, matching CPython's `exc.pos`.
pub pos: usize,
/// 1-based line of the error, matching CPython's `exc.lineno`.
pub lineno: usize,
/// 1-based column of the error, matching CPython's `exc.colno`.
pub colno: usize,
}
Structured fields of a json.JSONDecodeError, mirroring CPython’s msg /
doc / pos / lineno / colno exception attributes.
As with UnicodeErrorData, the payload exists so host bindings can
construct a real json.JSONDecodeError instead of falling back to a plain
ValueError; sandboxed code never sees these fields. lineno/colno are
carried explicitly rather than recomputed from doc because doc may be
absent (see JsonErrorData::MAX_DOC_LEN).
pub const MAX_DOC_LEN: usize = _;
Document size cap, mirroring UnicodeErrorData::MAX_OBJECT_LEN:
exception payloads are copied into the host once they escape the worker,
so doc is dropped (not truncated — a partial
document would misplace pos) for larger inputs.
pub fn build(msg: &str, doc: &[u8], pos: usize, lineno: usize, colno: usize) -> ExcData
Builds the payload for a decode error on doc, omitting the document
when it exceeds Self::MAX_DOC_LEN or is not valid UTF-8.
Implements: Clone, Debug, Deserialize<'de>, Hash, PartialEq, Serialize, StructuralPartialEq.
pub struct MontyException { /* private fields */ }
Public representation of a Monty exception.
pub fn new(exc_type: ExcType, message: Option<String>) -> Self
Create a new MontyException with the given exception type and message.
You can’t provide a traceback here, it’s send when raising the exception.
pub fn with_traceback(
exc_type: ExcType,
message: Option<String>,
traceback: Vec<StackFrame>,
) -> Self
Creates an exception with an explicit traceback.
Most callers should use MontyException::new — the traceback is
normally attached when the exception is raised. This constructor
exists for boundaries that reconstruct an exception that was raised
elsewhere (e.g. deserializing one received from a monty subprocess
worker) and must preserve its original frames.
pub fn with_data(self, data: ExcData) -> Self
Attaches a structured payload — see ExcData. Public for
boundaries that reconstruct an exception raised elsewhere (like
MontyException::with_traceback); in-process raises attach the
payload at the raise site instead.
pub fn data(&self) -> &ExcData
The structured payload, ExcData::None for most exceptions.
pub fn unicode_data(&self) -> Option<&UnicodeErrorData>
Structured UnicodeDecodeError/UnicodeEncodeError fields, present
only for unicode errors raised by codec operations on objects no
larger than UnicodeErrorData::MAX_OBJECT_LEN.
pub fn json_data(&self) -> Option<&JsonErrorData>
Structured json.JSONDecodeError fields, present only for decode
errors raised by json.loads (not for manually raised exceptions).
pub fn take_data(&mut self) -> ExcData
Removes and returns the structured payload, for consumers (like the Python bindings) that rebuild the native exception and want the payload by value without cloning it.
pub fn add_traceback(&mut self, traceback: impl IntoIterator<Item = StackFrame>)
Appends frames to this exception’s traceback.
pub fn runtime_error(err: impl fmt::Display) -> Self
Shorthand for a traceback-free RuntimeError wrapping err’s display
output — used at host boundaries (input conversion, REPL feeds) where
no sandbox stack frames exist.
pub fn exc_type(&self) -> ExcType
The exception type raised.
pub fn message(&self) -> Option<&str>
Optional exception message explaining what went wrong.
Equivalent of python’s exc.args[0]
pub fn into_message(self) -> Option<String>
Optional exception message explaining what went wrong.
This takes ownership of the MontyException and returns an owned String.
Equivalent of python’s exc.args[0]
pub fn traceback(&self) -> &[StackFrame]
Stack trace of the exception, first is the outermost frame shown first in the traceback
pub fn summary(&self) -> String
Returns a compact summary of the exception.
Format: ExceptionType: message (e.g., NotImplementedError: feature not supported)
If there’s no message, just returns the exception type name.
pub fn py_repr(&self) -> String
Returns the exception formatted as Python’s repr() would display it.
Format: ExceptionType('message') (e.g., ValueError('invalid value'))
Uses appropriate quoting for messages containing quotes.
Implements: Clone, Debug, Deserialize<'de>, Display, Error, From<MontyException>, PartialEq, Serialize, StructuralPartialEq.
pub struct StackFrame {
/// The filename where the code is located.
pub filename: String,
/// Start position in the source code.
pub start: CodeLoc,
/// End position in the source code.
pub end: CodeLoc,
/// The name of the frame (function name, or None for module-level code).
pub frame_name: Option<String>,
/// The source code line for preview in the traceback.
///
/// Stored as `Arc<str>` rather than `String` so that consecutive frames
/// referencing the same source line — typical of recursion and tight
/// helper-function loops — share a single allocation. Without sharing, a
/// 1000-deep recursive call into code on a long line would clone the
/// entire line into each frame and amplify memory usage by the call
/// depth. Serialization roundtrips lose the sharing (each frame gets
/// its own `Arc`), but that is bounded by the wire size of the
/// traceback so does not regress the amplification.
pub preview_line: Option<std::sync::Arc<str>>,
/// Whether to hide the caret marker in the traceback for this frame.
///
/// Set to `true` for:
/// - `raise` statements (CPython doesn't show carets for raise)
/// - `AttributeError` on attribute access (CPython doesn't show carets for these)
pub hide_caret: bool,
/// Whether to hide the `, in <name>` part of the frame line.
///
/// Set to `true` for `SyntaxError` where CPython doesn't show the frame name.
/// CPython's SyntaxError format: ` File "...", line N`
/// vs runtime error format: ` File "...", line N, in <module>`
pub hide_frame_name: bool,
}
A single frame in a Python traceback.
Contains all the information needed to display a traceback line: the file location, function name, and optional source code preview.
Monty uses only ~ characters for caret markers in tracebacks, unlike CPython 3.11+
which uses ~ for the function name and ^ for arguments (e.g., ~~~~~~~~~~~^^^^^^^^^^^).
This simplification is intentional - Monty marks the entire expression span uniformly.
Implements: Clone, Debug, Deserialize<'de>, Display, PartialEq, Serialize, StructuralPartialEq.
pub struct UnicodeErrorData {
/// The codec name as CPython reports it, e.g. `"utf-8"`, `"ascii"`.
pub encoding: String,
/// The full input that failed to encode/decode (`str` for encode errors,
/// `bytes` for decode errors), matching CPython's `exc.object`.
pub object: UnicodeErrorObject,
/// Start of the failing range: a character index for encode errors, a
/// byte offset for decode errors.
pub start: usize,
/// Exclusive end of the failing range, in the same units as `start`.
pub end: usize,
/// CPython's reason wording, e.g. `"ordinal not in range(128)"`.
pub reason: String,
}
Structured fields of a UnicodeDecodeError / UnicodeEncodeError,
mirroring CPython’s encoding / object / start / end / reason
exception attributes.
Monty exceptions are otherwise message-only; unicode errors additionally
carry these fields so host bindings (e.g. pydantic_monty) can construct
real UnicodeDecodeError / UnicodeEncodeError instances instead of
falling back to a plain ValueError. The payload is omitted when the
offending object is larger than UnicodeErrorData::MAX_OBJECT_LEN —
exceptions can be stored and copied outside the sandbox’s resource
tracker, so an unbounded payload would let huge inputs evade memory
limits. Sandboxed code never sees these fields (in-sandbox exceptions
expose only args).
pub const MAX_OBJECT_LEN: usize = _;
Payload size cap: unicode errors on objects larger than this carry no
structured data (hosts fall back to the message-only ValueError).
Exception payloads are copied into the host once they escape the worker,
so the cap bounds how much host memory a single raise can pin.
pub fn encode(
encoding: &str,
object: &str,
start: usize,
end: usize,
reason: &str,
) -> ExcData
Builds the payload for an encode error on object, or
ExcData::None when object exceeds Self::MAX_OBJECT_LEN.
pub fn decode(
encoding: &str,
object: &[u8],
start: usize,
end: usize,
reason: &str,
) -> ExcData
Builds the payload for a decode error on object, or
ExcData::None when object exceeds Self::MAX_OBJECT_LEN.
Public so monty-fs can build the payload for text-mode file reads.
Implements: Clone, Debug, Deserialize<'de>, Hash, PartialEq, Serialize, StructuralPartialEq.
pub enum UnicodeErrorObject {
/// A decode error's input `bytes`.
Bytes(Vec<u8>),
/// An encode error's input `str`.
Str(String),
}
The object attribute of a unicode error: the input being converted.
Implements: Clone, Debug, Deserialize<'de>, Hash, PartialEq, Serialize, StructuralPartialEq.
pub fn unicode_decode_error_msg(
codec: &str,
first_byte: u8,
start: usize,
end: usize,
reason: &str,
) -> String;
Formats the message for a UnicodeDecodeError covering the byte range
start..end: CPython’s single-byte form (byte 0x\{first_byte:02x\} in position \{start\}) when the range is one byte, otherwise the range form
(bytes in position {start}-{end - 1}).
A free function (rather than folded into ExcType::unicode_decode_error),
public and re-exported at the crate root, so monty-fs can produce the
identical wording when converting a MountError::InvalidUtf8 from a
text-mode file read into an exception.
pub enum FileMode {
/// `r` / `rb`: read-only; the file must already exist.
Read(bool),
/// `r+` / `rb+`: read and write an existing file. Reserved; not yet
/// produced by `FromStr`.
ReadUpdate(bool),
/// `w` / `wb`: write-only; truncate the file (creating it if missing) on open.
Write(bool),
/// `w+` / `wb+`: read and write; truncate the file (creating it if missing).
/// Reserved; not yet produced by `FromStr`.
WriteUpdate(bool),
/// `a` / `ab`: write-only appending; create the file if missing, preserving content.
Append(bool),
/// `a+` / `ab+`: read and append; create the file if missing, preserving content.
/// Reserved; not yet produced by `FromStr`.
AppendUpdate(bool),
}
A parsed Python open() mode.
This single enum captures everything that matters about how a file was
opened: the access pattern (r/w/a and the + update flag) and
whether the file is binary. The variant name encodes the access pattern;
the bool payload is true for binary and false for text — i.e.
Read(true) is 'rb' and Read(false) is 'r'.
Construct one with the FromStr impl (mode_str.parse::<FileMode>()).
The original input string is
intentionally not preserved; FileMode::as_str rebuilds the canonical
CPython form ('r', 'rb+', 'wb', …), matching how CPython itself
normalizes input like 'rt' → 'r' and 'r+b' → 'rb+'.
+ update modes (ReadUpdate/WriteUpdate/AppendUpdate) are reserved
in the enum so the mode space is fully represented, but FromStr
currently rejects them — properly modelling them needs read-position
tracking that the file wrapper does not yet implement. Treat the Update
variants as unreachable at runtime; do not pattern-match against them as
if they were a valid result of parsing user input.
Carried publicly by MontyObject::FileHandle so a host servicing file
operations can inspect the mode without re-parsing the raw string.
pub fn as_str(&self) -> &'static str
Returns the canonical Python open() mode string for this mode,
matching what CPython exposes via file.mode.
The result is always one of the 12 well-formed mode strings (r, rb,
r+, rb+, w, wb, w+, wb+, a, ab, a+, ab+). This is
the canonical form CPython itself normalizes user input into — e.g.
'rt' → 'r', 'r+b' → 'rb+', 'br' → 'rb'.
pub fn is_binary(&self) -> bool
Whether the file is binary ('rb', 'wb', …) rather than text.
pub fn readable(&self) -> bool
Whether read() is allowed by this mode.
pub fn writable(&self) -> bool
Whether write() is allowed by this mode.
pub fn is_append(&self) -> bool
Whether writes should always append (a/a+).
pub fn truncate(&self) -> bool
Whether open() must truncate the file to empty immediately (w/w+).
pub fn create(&self) -> bool
Whether open() must create the file immediately if missing.
True for the w/w+ and a/a+ families. For append modes this must
not disturb existing content.
pub fn type_name(&self) -> &'static str
Returns the bare Python type name (type(f).__name__) for this mode.
pub fn file_type_name(&self) -> &'static str
Returns the fully-qualified _io wrapper type name a file opened with
this mode presents as, matching CPython’s repr(f) (e.g.
"_io.TextIOWrapper"). The module-less form is type_name.
Implements: Clone, Copy, Debug, Deserialize<'de>, Eq, FromStr, Hash, PartialEq, Serialize, StructuralPartialEq, ToMontyObject.
pub struct FormatFloat(pub f64);
A Display adapter that writes a float exactly as CPython’s
repr()/str() (identical for floats in Python 3): the shortest decimal
string that round-trips, switching to scientific notation when the base-10
exponent is < -4 or >= 16, and always keeping at least one fractional
digit (1.0, never 1) — 1e16 → "1e+16", 1234.5 → "1234.5",
inf/nan lowercased.
This is the default rendering for a bare f"{x}", str(x), repr(x) and
floats inside container reprs — not the format mini-language (that’s
format_float_g et al, in monty). Rust can’t do this directly: its f64 Display
never uses scientific notation (1e16 prints as 10000000000000000) and
renders NaN as "NaN".
As a Display adapter it writes straight to the caller’s sink with no
heap allocation: it borrows Rust’s shortest-digits guarantee via {:e}
into a small stack buffer (an f64 {:e} is ASCII and ≤ 24 bytes) and
re-lays-out those digits per CPython’s rules.
Implements: Display.
pub struct StringRepr<'a>(pub &'a str);
Formatter for a Python repr() string.
Implements: Debug, Display.
pub fn bytes_repr(bytes: &[u8]) -> String;
Returns a CPython-compatible repr string for bytes.
Convenience wrapper around bytes_repr_fmt that returns an owned String.
pub fn bytes_repr_fmt(bytes: &[u8], f: &mut impl Write) -> fmt::Result;
Writes a CPython-compatible repr string for bytes to a formatter.
Format: b'...' or b"..." depending on content.
- Uses single quotes by default
- Switches to double quotes if bytes contain
'but not" - Escapes:
\\,\t,\n,\r,\xNNfor non-printable bytes
pub fn string_repr_fmt(s: &str, f: &mut impl Write) -> fmt::Result;
Writes a Python repr() string for a given string slice to a formatter.
Quote choice matches CPython: single quotes by default, switching to double
quotes only when the string contains a ' but no " (so the quote needn’t
be escaped). Backslash, the active quote, and \n/\t/\r use the short
escapes; any other non-printable character is escaped numerically
(\xNN/\uNNNN/\UNNNNNNNN), e.g. repr('\x00') == "'\\x00'" and
repr('\xa0') == "'\\xa0'".
“Non-printable” matches CPython’s str.isprintable (see
repr_needs_escape): Unicode categories C* and Z*, except the ASCII
space. Category data comes from unicode-general-category, whose Unicode
version may differ slightly from CPython’s, affecting only recently
(re)assigned code points.
pub fn utf8_error_reason(first_bad_byte: u8, error_len: Option<usize>) -> &'static str;
Classifies an invalid-UTF-8 error into CPython’s reason wording, from the
first unexpected byte and Utf8Error::error_len().
error_len == None means the input ended mid-sequence (unexpected end of data); otherwise a byte that is a legal multi-byte lead (0xC2–0xF4) was
followed by an invalid continuation, and anything else (stray
continuation bytes, the overlong leads 0xC0/0xC1, 0xF5–0xFF) is an
invalid start byte. Public (re-exported at the crate root) so monty-fs
produces identical wording for text-mode file reads.
pub const DEFAULT_MAX_PRINT_COLLECT_BYTES: usize = 10_485_760usize;
Default cap for PrintWriter::CollectString / PrintWriter::CollectStreams
and the matching Python collectors.
Host-side print buffers sit outside ResourceLimits::max_memory;
without a cap, a print loop can OOM the host while sandbox limits stay green.
Pass max_bytes: None to opt out on trusted hosts.
pub enum PrintStream {
/// Standard output — the default for every `print()` call today.
Stdout,
/// Standard error — reserved for future `print(..., file=sys.stderr)` support.
Stderr,
}
Identifies the output stream for a single print fragment.
Today the print() builtin only writes to Stdout. The Stderr variant is
included for forward compatibility with a future print(..., file=sys.stderr)
implementation so the collected-output API shape does not have to change when
that lands.
Implements: Clone, Copy, Debug, Eq, PartialEq, StructuralPartialEq.
pub enum PrintWriter<'a> {
/// Silently discard all output.
Disabled,
/// Write to standard output.
Stdout,
/// Collect all output into a single `String`, in emit order, with no stream labels.
///
/// Second field: max collected bytes (`None` = unlimited). Exceeding raises
/// `MemoryError` with the same message as `ResourceError::Memory`.
CollectString(&'a mut String, Option<usize>),
/// Collect all output as `(stream, text)` tuples.
///
/// The builtin `print()` implementation calls `stdout_write` for each argument
/// and `stdout_push` for each separator/terminator. To avoid one tuple per
/// fragment, this variant appends to the trailing tuple when it already matches
/// the current stream; a new tuple is only pushed when the stream changes.
/// So long as every write targets the same stream (the status quo today, since
/// `print()` only writes to stdout), a single `print(a, b)` call produces one
/// `(Stdout, "a b\n")` entry — and consecutive prints with `end=''` likewise
/// merge into a single trailing entry.
///
/// Second field: max collected bytes across all tuples (`None` = unlimited).
CollectStreams(&'a mut Vec<(PrintStream, String)>, Option<usize>),
/// Delegate to a custom callback.
Callback(&'a mut dyn PrintWriterCallback),
}
Output handler for the print() builtin function.
Provides common output modes as enum variants to avoid trait object overhead
in the typical cases (stdout, disabled, collect). For custom output handling,
use the Callback variant with a PrintWriterCallback implementation.
Disabled— silently discards all output (useful for benchmarking or suppressing output).Stdout— writes to standard output (the default behavior).CollectString— accumulates output into a targetStringfor programmatic access. No stream labels are preserved; every fragment is appended in the order it was emitted. TheOption<usize>is an optional byte cap (None= unlimited); constructorscollect_string/ default Python collectors useDEFAULT_MAX_PRINT_COLLECT_BYTES.CollectStreams— accumulates output as(stream, text)pairs, merging consecutive same-stream fragments into one tuple. Each write to the same stream extends the trailing entry rather than producing a new one; a new tuple is only pushed when the stream changes. Same optional byte cap asCollectString.Callback— delegates to a user-providedPrintWriterCallbackimplementation.
pub fn collect_string(buf: &mut String) -> PrintWriter<'_>
Collect into buf with the default DEFAULT_MAX_PRINT_COLLECT_BYTES cap.
pub fn collect_streams(buf: &mut Vec<(PrintStream, String)>) -> PrintWriter<'_>
Collect into buf with the default DEFAULT_MAX_PRINT_COLLECT_BYTES cap.
pub fn reborrow(&mut self) -> PrintWriter<'_>
Creates a new PrintWriter that reborrows the same underlying target.
This is useful in iterative execution (start/resume loops) where each
step takes PrintWriter by value but you want all steps to write to the
same output target. The original writer remains valid after the reborrowed
copy is dropped.
pub fn stdout_write(&mut self, output: Cow<'_, str>) -> Result<(), MontyException>
Called once for each formatted argument passed to print().
This method writes only the given argument’s text, without adding
separators or a trailing newline. Separators (spaces) and the final
terminator (newline) are emitted via stdout_push.
pub fn stdout_push(&mut self, end: char) -> Result<(), MontyException>
Appends a single character to the output.
Generally called to add spaces (separators) and newlines (terminators) within print output.
pub trait PrintWriterCallback {
fn stdout_write(&mut self, output: Cow<'_, str>) -> Result<(), MontyException>;
fn stdout_push(&mut self, end: char) -> Result<(), MontyException>;
}
Trait for custom output handling from the print() builtin function.
Implement this trait and pass it via PrintWriter::Callback to capture
or redirect print output from sandboxed Python code.
Called once for each formatted argument passed to print().
This method is responsible for writing only the given argument’s text, and must
not add separators or a trailing newline. Separators (such as spaces) and the
final terminator (such as a newline) are emitted via stdout_push.
output- The formatted output string for a single argument (without separators or trailing newline).
Add a single character to stdout.
Generally called to add spaces and newlines within print output.
end- The character to print after the formatted output.
pub fn check_print_collect_limit(
current_len: usize,
add: usize,
max_bytes: Option<usize>,
) -> Result<(), MontyException>;
Rejects a collect-buffer growth that would exceed max_bytes.
None means unlimited. On overflow, returns the same MemoryError message
as ResourceError::Memory so hosts see one familiar limit string.
pub struct ConversionError {
/// The type name that was expected (e.g., "int", "str").
pub expected: &'static str,
/// The actual type name of the `MontyObject` (e.g., "list", "NoneType",
/// or a class instance's class name).
pub actual: String,
}
Error returned when a MontyObject cannot be converted to the requested Rust type.
This error is returned by the TryFrom implementations when attempting to extract
a specific type from a MontyObject that holds a different variant.
pub fn new(expected: &'static str, actual: impl Into<String>) -> Self
Creates a new ConversionError with the expected and actual type names.
Implements: Debug, Display, Error.
pub struct DictPairs(/* private */);
A collection of key-value pairs representing Python dictionary contents.
Used internally by MontyObject::Dict to store dictionary entries while preserving
insertion order. Keys and values are both MontyObject instances.
pub fn len(&self) -> usize
Number of (key, value) pairs held by this dict.
pub fn is_empty(&self) -> bool
Whether this dict has no pairs.
pub fn iter(&self) -> impl Iterator<Item = &(MontyObject, MontyObject)>
Iterates the (key, value) pairs in insertion order.
Implements: Clone, Debug, Default, Deserialize<'de>, Eq, From<Vec<(MontyObject, MontyObject)>>, FromIterator<(MontyObject, MontyObject)>, IntoIterator, PartialEq, Serialize, StructuralPartialEq.
pub enum InvalidInputError {
/// The input type is not valid for conversion to a runtime Value.
/// Message explaining why the type is invalid.
InvalidType(std::borrow::Cow<'static, str>),
/// A resource limit was exceeded during conversion.
Resource(ResourceError),
}
Error returned when a MontyObject cannot be used as an input to code execution.
This can occur when:
- A
MontyObjectvariant (likeRepr) is only valid as an output, not an input - A resource limit is exceeded during conversion
pub fn invalid_type(msg: impl Into<Cow<'static, str>>) -> Self
Creates a new InvalidInputError for the given type name.
Implements: Clone, Debug, Display, Error, From<ResourceError>.
pub const MAX_TIMEZONE_OFFSET_SECONDS: i32 = 86_399;
Largest UTC offset datetime.timezone accepts, +23:59:59.
See MIN_TIMEZONE_OFFSET_SECONDS.
pub const MIN_TIMEZONE_OFFSET_SECONDS: i32 = -86_399;
Smallest UTC offset datetime.timezone accepts, -23:59:59.
CPython requires an offset strictly inside ±24 hours. Shared with the wire decoder so a forged offset is rejected at the boundary rather than by the sandbox-side constructor, which by then can only report a generic bad value.
pub struct MontyClassInstance {
/// The instance's class (never a builtin type).
pub class_type: MontyClassType,
/// Identity of the instance, generated by whichever side defined it.
pub instance_id: MontyUuid,
/// Eagerly-sent attribute name -> value mapping, in order.
pub attrs: DictPairs,
}
A class instance crossing the sandbox boundary — the payload of
MontyObject::ClassInstance.
Host-backed instances carry a host-generated uuid as instance_id, so
method calls and lazy attribute lookups on names missing from attrs
suspend back to the host, routed by that id (public names only).
Sandbox-defined instances carry a worker-generated uuid instead; either
way the id never encodes a memory address.
Implements: Clone, Debug, Deserialize<'de>, Eq, PartialEq, Serialize, StructuralPartialEq.
pub struct MontyClassType {
/// The Python-visible class name (e.g. `"Point"`).
pub name: String,
/// Identity of the class, generated by whichever side defined it.
pub id: MontyUuid,
/// True for a host-defined class (wire origin `HOST`); false for a
/// sandbox-defined class (`SANDBOX`). Informational: the sandbox resolves
/// `id` against its live objects either way, and consults this only to
/// reject a sandbox id it no longer knows. Builtins never use `MontyClassType`.
pub host_defined: bool,
/// Whether `dataclasses.is_dataclass` is true for the class.
pub is_dataclass: bool,
/// Class attributes sent eagerly with the type object (class constants,
/// per the sending wrapper's policy), on every crossing of the class as a
/// value or as the type branch of an instance. The sandbox keeps one type
/// object per class id: a non-empty set replaces its attrs, an empty set
/// (no policy, or a type crossing out) leaves them unchanged.
pub attrs: DictPairs,
}
A non-builtin class type object crossing the sandbox boundary — the
payload of MontyType::Instance and the class half of
MontyClassInstance.
id is generated by whichever side defined the class (host uuid4, or a
worker uuid for sandbox classes); the sandbox keys its single type object
per class on it and routes instantiation and classmethod calls by it. It
never encodes an address. PartialEq compares every field, attrs
included, not just id.
Implements: Clone, Debug, Deserialize<'de>, Eq, PartialEq, Serialize, StructuralPartialEq.
pub struct MontyDate {
/// Gregorian year in range 1..=9999.
pub year: i32,
/// Month component in range 1..=12.
pub month: u8,
/// Day component valid for the given month/year.
pub day: u8,
}
A Python datetime.date value with year, month, and day components.
Implements: Clone, Debug, Deserialize<'de>, Eq, Hash, PartialEq, Serialize, StructuralPartialEq.
pub struct MontyDateTime {
/// Gregorian year in range 1..=9999.
pub year: i32,
/// Month component in range 1..=12.
pub month: u8,
/// Day component valid for the given month/year.
pub day: u8,
/// Hour in range 0..=23.
pub hour: u8,
/// Minute in range 0..=59.
pub minute: u8,
/// Second in range 0..=59.
pub second: u8,
/// Microsecond in range 0..=999_999.
pub microsecond: u32,
/// Fixed offset seconds for aware datetimes, or `None` for naive values.
///
/// Within `MIN_TIMEZONE_OFFSET_SECONDS`..=`MAX_TIMEZONE_OFFSET_SECONDS` when set.
pub offset_seconds: Option<i32>,
/// Optional explicit timezone name for aware datetimes.
///
/// Must be `None` when `offset_seconds` is `None`.
pub timezone_name: Option<String>,
}
A Python datetime.datetime value with date, time, and optional timezone components.
Implements: Clone, Debug, Deserialize<'de>, Eq, Hash, PartialEq, Serialize.
pub struct MontyFileHandle {
/// The virtual (sandbox) path of the file. Never a host path.
pub path: String,
/// The parsed `open()` mode.
pub mode: FileMode,
/// Position for sized/line/seek operations: char index in text mode,
/// byte index in binary mode. `0` for a freshly opened file.
pub position: u64,
}
An open file object (the result of open()).
This is the boundary representation of Monty’s heap OpenFile
wrapper. It carries everything needed to service a file operation from a
host that holds no live OS handle: the virtual path, the mode, and
the byte position for seek-aware reads.
The host produces a FileHandle as the result of an
OsFunctionCall::Open call; the
interpreter then builds its heap file wrapper from it. Conversely, a heap file
object passed as an argument to a read/write OS call is converted
back to a FileHandle so the host receives this state.
Implements: Clone, Debug, Deserialize<'de>, Display, Serialize.
pub enum MontyObject {
/// Python's `Ellipsis` singleton (`...`).
Ellipsis,
/// Python's `NotImplemented` singleton.
NotImplemented,
/// Python's `None` singleton.
None,
/// Python boolean (`True` or `False`).
Bool(bool),
/// Python integer (64-bit signed).
Int(i64),
/// Python arbitrary-precision integer (larger than i64).
BigInt(num_bigint::BigInt),
/// Python float (64-bit IEEE 754).
Float(f64),
/// Python string (UTF-8).
String(String),
/// Python bytes object.
Bytes(Vec<u8>),
/// Python list (mutable sequence).
List(Vec<Self>),
/// Python tuple (immutable sequence).
Tuple(Vec<Self>),
/// Python named tuple (immutable sequence with named fields).
///
/// Named tuples behave like tuples but also support attribute access by field name.
/// The type_name is used in repr (e.g., "os.stat_result"), and field_names provides
/// the attribute names for each position.
NamedTuple { type_name: String, field_names: Vec<String>, values: Vec<Self> },
/// Python dictionary (insertion-ordered mapping).
Dict(DictPairs),
/// Python set (mutable, unordered collection of unique elements).
Set(Vec<Self>),
/// Python frozenset (immutable, unordered collection of unique elements).
FrozenSet(Vec<Self>),
/// Python `datetime.date`.
Date(MontyDate),
/// Python `datetime.datetime`.
DateTime(MontyDateTime),
/// Python `datetime.time`.
Time(MontyTime),
/// Python `datetime.timedelta`.
TimeDelta(MontyTimeDelta),
/// Python `datetime.timezone` fixed-offset timezone.
TimeZone(MontyTimeZone),
/// Python exception with type and optional message argument.
Exception { exc_type: ExcType, arg: Option<String> },
/// A Python type object (e.g., `int`, `str`, `list`).
///
/// Returned by the `type()` builtin and can be compared with other types.
Type(MontyType),
BuiltinFunction(BuiltinsFunctions),
/// Python `pathlib.Path` object (or technically a `PurePosixPath`).
///
/// Represents a filesystem path. Can be used both as input (from host) and output.
Path(String),
/// An open file object (the result of `open()`).
FileHandle(MontyFileHandle),
/// A class instance crossing the sandbox boundary (see `MontyClassInstance`).
/// Boxed: the payload is larger than every other variant and would grow
/// `MontyObject` (and so every container element) otherwise.
ClassInstance(Box<MontyClassInstance>),
/// An external function provided by the host.
///
/// Returned by the host in response to a `NameLookup` to provide a callable
/// that the VM can invoke. When called, the VM yields `FunctionCall` to the host.
Function { name: String, docstring: Option<String> },
/// Fallback for values that cannot be represented as other variants.
///
/// Contains the `repr()` string of the original value.
///
/// This is output-only and cannot be used as an input to the interpreter.
Repr(String),
/// Represents a cycle detected during Value-to-MontyObject conversion.
///
/// When converting cyclic structures (e.g., `a = []; a.append(a)`), this variant
/// is used to break the infinite recursion. Contains an opaque identity token
/// (the raw heap index of the object the cycle points back to — meaningful only
/// for equality, and only within the result that produced it) and the
/// type-specific placeholder string (e.g., `"[...]"` for lists, `"{...}"` for
/// dicts). Two `Cycle` values compare equal if they refer to the same object.
///
/// This is output-only and cannot be used as an input to the interpreter.
Cycle(usize, String),
}
An owned Python value exchanged between Monty and its host.
Construct MontyObject values to provide globals, external-function
results, and other inputs to sandboxed code. Execution results and values
passed to host callbacks use the same representation.
Most common Python values have a direct variant, including nested
collections and datetime values. Repr and
Cycle can only appear in output because they cannot be
reconstructed as executable Python values. Exception
can be used both to raise an exception and to represent one returned by
execution.
Collections are owned snapshots: modifying a returned MontyObject does
not modify the corresponding value in a running session.
Only immutable variants implement Hash, including the datetime family
(Date, DateTime, TimeDelta, TimeZone). Attempting to hash mutable
variants (List, Dict) will panic.
The derived Serialize / Deserialize impls use an externally tagged
format ({"Int": 42}, {"String": "hi"}, …). This is what postcard
and serde_json::to_string(&obj) produce. It is lossless and designed
for snapshots and binary transport, not for human-facing JSON.
pub fn dict(dict: impl Into<DictPairs>) -> Self
Creates a new MontyObject from something that can be converted into a DictPairs.
pub fn builtin_function_from_name(name: &str) -> Option<Self>
Resolves a builtin function by its Python name (e.g. "len").
The BuiltinsFunctions enum inside MontyObject::BuiltinFunction is
crate-private, so boundaries that serialize a builtin function by name
(e.g. the subprocess wire protocol) use this to reconstruct the variant.
The name matches the variant’s Display output.
pub const fn host_base_size() -> usize
Returns the fixed host footprint charged for each decoded object.
pub const fn host_metadata_string_size(value: &str) -> usize
Returns the host footprint of one owned string in a metadata vector.
pub fn host_size(&self) -> usize
Shallow host footprint of a freshly decoded obj: the fixed MontyObject
size plus any leaf payload it owns directly (string/bytes/bigint bytes, and
the Vec<String> field names of structured values, which aren’t themselves
MontyObjects and would otherwise be uncharged). Boxed payloads
(ClassInstance, Type(Instance)) charge their heap allocation plus the
class name; their eager attrs are charged like container elements.
Container elements are excluded — each charges its own size via
monty-proto’s decode_field, so a list charges size_of::<MontyObject>() here.
pub fn deep_host_size(&self) -> usize
Returns the recursively expanded host footprint used by transport budgets.
Unlike Self::host_size, this includes every value stored in a container.
pub fn py_repr(&self) -> String
Returns the Python repr() string for this value.
Could panic if out of memory.
pub fn is_truthy(&self) -> bool
Returns true if this value is “truthy” according to Python’s truth testing rules.
In Python, the following values are considered falsy:
NoneandEllipsisFalse- Zero numeric values (
0,0.0) - Empty sequences and collections (
"",b"",[],(),{})
All other values are truthy, including Exception and Repr variants.
pub fn type_name(&self) -> &str
Returns the Python type name for this value (e.g., "int", "str", "list").
These are the same names returned by Python’s type(x).__name__; a
class instance reports its class name ("Point").
Implements: AsRef<MontyObject>, Clone, Debug, Deserialize<'de>, Display, Eq, From<MontyObject>, Hash, PartialEq, Serialize, ToMontyObject, TryFrom<&MontyObject>.
pub struct MontyTime {
/// Hour in range 0..=23.
pub hour: u8,
/// Minute in range 0..=59.
pub minute: u8,
/// Second in range 0..=59.
pub second: u8,
/// Microsecond in range 0..=999_999.
pub microsecond: u32,
/// Fixed offset seconds for aware times, or `None` for naive values.
///
/// Within `MIN_TIMEZONE_OFFSET_SECONDS`..=`MAX_TIMEZONE_OFFSET_SECONDS` when set.
pub offset_seconds: Option<i32>,
/// Optional explicit timezone name for aware times.
///
/// Must be `None` when `offset_seconds` is `None`.
pub timezone_name: Option<String>,
/// Fold flag, 0 or 1.
pub fold: u8,
}
A Python datetime.time value: a wall clock with no date attached.
fold is carried so the flag survives the boundary, but neither monty nor
this type interprets it — as in CPython it takes no part in equality.
Implements: Clone, Debug, Deserialize<'de>, Eq, Hash, PartialEq, Serialize.
pub struct MontyTimeDelta {
/// Day component.
pub days: i32,
/// Seconds component in normalized range 0..86400.
pub seconds: i32,
/// Microseconds component in normalized range 0..1_000_000.
pub microseconds: i32,
}
A Python datetime.timedelta value representing a duration.
Implements: Clone, Debug, Deserialize<'de>, Eq, Hash, PartialEq, Serialize, StructuralPartialEq.
pub struct MontyTimeZone {
/// Fixed UTC offset in seconds, within `MIN_TIMEZONE_OFFSET_SECONDS`..=`MAX_TIMEZONE_OFFSET_SECONDS`.
pub offset_seconds: i32,
/// Optional display name.
pub name: Option<String>,
}
A Python datetime.timezone fixed-offset timezone.
Implements: Clone, Debug, Deserialize<'de>, Eq, Hash, PartialEq, Serialize.
pub enum MontyType {
Ellipsis,
Type,
NoneType,
Bool,
Int,
Float,
Range,
Slice,
/// The four `datetime` classes carry the qualified names the runtime
/// `Type` uses (`datetime.date`, ...) rather than bare `date`, so a type
/// object keeps one name either side of the boundary.
Date,
DateTime,
TimeDelta,
TimeZone,
Str,
Bytes,
List,
/// `collections.deque`. Qualified like `datetime.datetime` so the
/// host-boundary name matches the runtime `Type::Deque` (`collections.deque`)
/// rather than a bare `deque`.
Deque,
ListIterator,
CallableIterator,
Tuple,
NamedTuple,
Dict,
DictKeys,
DictItems,
DictValues,
Set,
FrozenSet,
/// A non-builtin class type object — a sandbox-defined or host-defined
/// class, carrying the resolved `MontyClassType` (name, uuid, flags).
/// Sandbox class types are output-only (rejected as inputs); host class
/// types round-trip.
///
/// `#[strum(disabled)]`: excluded from `EnumIter` (no meaningful default
/// name; the name round-trip tests iterate the nameable variants only).
Instance(Box<MontyClassType>),
/// Exception types render/parse via `ExcType`'s own strum name
/// (`"ValueError"`, `"json.JSONDecodeError"`, ...), so this variant is
/// `#[strum(disabled)]`: `name` and
/// `from_type_name` peel `Exception` off
/// explicitly.
Exception(ExcType),
Function,
BuiltinFunction,
Cell,
Iterator,
Coroutine,
Module,
TextIOWrapper,
BufferedReader,
BufferedWriter,
BufferedRandom,
SpecialForm,
Path,
Property,
RePattern,
ReMatch,
TupleIterator,
StrAsciiIterator,
StrIterator,
BytesIterator,
RangeIterator,
DictKeyIterator,
DictItemIterator,
DictValueIterator,
SetIterator,
ItertoolsCount,
ItertoolsRepeat,
/// A `dataclasses.Field` describing one field of a sandbox `@dataclass`,
/// as found in a class's `__dataclass_fields__`.
Field,
ItertoolsPairwise,
ItertoolsCompress,
ItertoolsIslice,
ItertoolsChain,
ItertoolsCycle,
NotImplementedType,
/// The `__dataclass_params__` of a sandbox `@dataclass`: the options it was
/// decorated with, named as CPython's private class reports itself.
DataclassParams,
ItertoolsTakeWhile,
ItertoolsDropWhile,
ItertoolsFilterFalse,
ItertoolsStarMap,
/// The builtin `object`, which the sandbox exposes as a name only — it is
/// not a base class and cannot be constructed.
Object,
Time,
/// `functools.partial`, qualified the way CPython's `tp_name` is.
Partial,
}
The Python type of a value at the host boundary — the public mirror of the
internal runtime Type enum.
Where the runtime Type::Instance carries a transient heap id, the public
MontyType::Instance carries the resolved MontyClassType (name, uuid,
flags), so a MontyType is always self-contained: it can be serialized,
sent over the subprocess wire protocol, and displayed without heap access.
A sandbox class type is output-only: its class binding cannot be
reconstructed host-side, so passing one back as an input is rejected with
an InvalidInputError. Host class types round-trip.
pub fn name(&self) -> &str
The Python-visible name of this type ("int", "datetime.datetime",
"ValueError", or the class name for Instance).
pub fn from_type_name(name: &str) -> Option<Self>
Parses a name produced by Display/name
back to the MontyType — the wire-protocol decode path for builtin
type names. Never yields Instance: class names
return None (the wire carries instance types in a dedicated field
instead), and "object" parses to the builtin Object.
EnumString parses via the same strum serialize attributes that
IntoStaticStr renders with, so the two stay in lockstep by
construction. Exception types display as their exception name
(“ValueError”, “json.JSONDecodeError”, …) — fall back to the
ExcType parser.
Implements: Clone, Debug, Deserialize<'de>, Display, Eq, From<&'_derivative_strum MontyType>, From<MontyType>, FromStr, IntoEnumIterator, PartialEq, Serialize, StructuralPartialEq, TryFrom<&str>, VariantNames.
pub struct GetenvArgs {
pub key: String,
pub default: MontyObject,
}
os.getenv(key, default=None) shape. The host decides whether to
substitute default when the variable is unset.
Implements: Clone, Debug, Deserialize<'de>, Serialize, ToArgs.
pub struct MkdirCallArgs {
pub path: MontyPath,
pub parents: bool,
pub exist_ok: bool,
}
mkdir(path, parents=False, exist_ok=False) shape. parents/exist_ok
are kw-only so ToArgs emits them as kwargs (matching CPython).
Implements: Clone, Debug, Deserialize<'de>, Serialize, ToArgs.
pub struct MontyPath(/* private */);
Owned virtual (sandbox) path carried by OS-call args.
String newtype: derefs to &str for fs/ routing, and ToMontyObject
projects it back to MontyObject::Path at the host boundary. Constructed
at the producer site after the source Value has been validated as a
path/string — never from raw input.
pub fn new(path: String) -> Self
pub fn as_str(&self) -> &str
pub fn into_string(self) -> String
Implements: Clone, Debug, Deref, Deserialize<'de>, Eq, From<&str>, From<String>, PartialEq, Serialize, StructuralPartialEq, ToMontyObject.
pub struct OpenCallArgs {
pub path: MontyPath,
pub mode: FileMode,
}
open(path, mode) shape. The mode is parsed into FileMode before
construction so the fs/ backend doesn’t re-parse; ToArgs re-serialises
it back to a MontyObject::String for the host.
Implements: Clone, Debug, Deserialize<'de>, Serialize, ToArgs.
pub enum OsFunctionCall {
/// Check if a path exists.
Exists(MontyPath),
/// Check if path is a regular file.
IsFile(MontyPath),
/// Check if path is a directory.
IsDir(MontyPath),
/// Check if path is a symbolic link.
IsSymlink(MontyPath),
/// Read file contents as text.
ReadText(MontyPath),
/// Read file contents as bytes.
ReadBytes(MontyPath),
/// `stat()` — return a stat result tuple.
Stat(MontyPath),
/// List directory contents.
Iterdir(MontyPath),
/// Resolve symlinks and return absolute path.
Resolve(MontyPath),
/// Absolute path without symlink resolution.
Absolute(MontyPath),
/// Write text to file (truncating).
WriteText(PathStringDataArgs),
/// Append text to file.
AppendText(PathStringDataArgs),
/// Write bytes to file (truncating).
WriteBytes(PathBytesDataArgs),
/// Append bytes to file.
AppendBytes(PathBytesDataArgs),
/// Open a file. The host performs the open-time effect (truncate for
/// `w`/`w+`, create-if-missing for `a`/`a+`, existence check for `r`/`r+`)
/// and returns a `MontyObject::FileHandle` — it never holds a live OS
/// handle across calls.
Open(OpenCallArgs),
/// Create directory (`parents`/`exist_ok` kwargs).
Mkdir(MkdirCallArgs),
/// Remove file.
Unlink(MontyPath),
/// Remove directory.
Rmdir(MontyPath),
/// Rename / move (src → dst).
Rename(RenameCallArgs),
/// Get an environment variable value.
Getenv(GetenvArgs),
/// Get the entire environment as a dictionary.
GetEnviron,
/// Get today's date from the host system (for `date.today()`).
DateToday,
/// Get the current date/time from the host system (for `datetime.now(tz=...)`).
/// Carries the timezone argument, `None` for a naive result.
DateTimeNow(Option<MontyTimeZone>),
}
Tagged dispatch value for OS-level operations.
Each variant carries the strongly-typed args/kwargs the corresponding OS
call needs. The fs/ layer matches on this enum directly (no MontyObject
introspection); host bindings get a generic (positional, keyword) view
via OsFunctionCall::to_args.
See the module docs for how to add a new variant.
pub fn name(&self) -> &'static str
Stable string name for this OS function — surfaces in
Self::on_no_handler errors, host os callbacks, and serialised
snapshots. The strum serialize string on each variant.
pub fn to_args(self) -> (Vec<MontyObject>, Vec<(MontyObject, MontyObject)>)
Projects this call’s args into (positional, keyword) MontyObject
vectors for delivery to a host callback.
pub fn is_write(&self) -> bool
Whether this call mutates filesystem state — the read-only-mount gate.
Open’s write-ness is mode-dependent (w/w+/a/a+ write; r/r+
don’t).
pub fn is_existence_check(&self) -> bool
Whether this operation checks existence without reading content.
Existence checks return false for nonexistent paths rather than
raising FileNotFoundError, matching CPython’s pathlib.Path.
pub fn embedded_null_message(&self, for_destination: bool) -> &'static str
CPython’s ValueError message for a path containing a null byte.
The wording is not uniform in CPython: it comes from whichever layer
first inspects the path, so the content operations go through open()
and say embedded null byte, while the metadata ones are named by the
syscall their os wrapper was about to make. for_destination picks
the rename argument that carried the byte.
pub fn fs_primary_path(&self) -> Option<&str>
The call’s primary path if it’s a FS operation, None otherwise.
Used for routing and error reporting.
pub fn rename_destination(&self) -> Option<&str>
The rename destination path, or None for every other variant — the
second routing key a mount table needs (both rename endpoints must
resolve to the same mount).
pub fn on_no_handler(&self) -> MontyException
Exception to raise when no handler accepted this call: PermissionError
for FS ops (with the path), RuntimeError for non-FS ops.
Implements: Clone, Debug, Deserialize<'de>, Display, From<&'_derivative_strum OsFunctionCall>, From<OsFunctionCall>, Serialize.
pub struct PathBytesDataArgs {
pub path: MontyPath,
pub data: Vec<u8>,
}
path + bytes data shape used by WriteBytes and AppendBytes.
Implements: Clone, Debug, Deserialize<'de>, Serialize, ToArgs.
pub struct PathStringDataArgs {
pub path: MontyPath,
pub data: String,
}
path + str data shape used by WriteText and AppendText.
Implements: Clone, Debug, Deserialize<'de>, Serialize, ToArgs.
pub struct RenameCallArgs {
pub src: MontyPath,
pub dst: MontyPath,
}
rename(src, dst) shape.
Implements: Clone, Debug, Deserialize<'de>, Serialize, ToArgs.
pub fn dir_stat(mode: i64, mtime: f64) -> MontyObject;
Creates a stat_result for a directory.
The directory type bits (0o040_000) are automatically added if not present.
mode- Directory permissions as octal. Common values:0o755- rwxr-xr-x (owner full, others read/execute)0o700- rwx------ (owner only)0o040755- same as 0o755 with explicit directory type bits
mtime- Modification time as Unix timestamp
pub fn file_stat(mode: i64, size: i64, mtime: f64) -> MontyObject;
Creates a stat_result for a regular file.
The file type bits (0o100_000) are automatically added if not present.
mode- File permissions as octal. Common values:0o644- rw-r—r— (owner read/write, others read)0o600- rw------- (owner read/write only)0o755- rwxr-xr-x (executable, owner full, others read/execute)0o100644- same as 0o644 with explicit file type bits
size- File size in bytesmtime- Modification time as Unix timestamp
pub fn stat_result(
st_mode: i64,
st_ino: i64,
st_dev: i64,
st_nlink: i64,
st_uid: i64,
st_gid: i64,
st_size: i64,
st_atime: f64,
st_mtime: f64,
st_ctime: f64,
) -> MontyObject;
Creates a full stat_result with all 10 fields specified.
This is the low-level builder; prefer file_stat(), dir_stat(), or symlink_stat()
for common cases.
pub fn symlink_stat(mode: i64, mtime: f64) -> MontyObject;
Creates a stat_result for a symbolic link.
The symlink type bits (0o120_000) are automatically added if not present.
mode- Symlink permissions as octal. Common values:0o777- rwxrwxrwx (symlinks typically have full permissions)0o120777- same as 0o777 with explicit symlink type bits
mtime- Modification time as Unix timestamp
pub static BASELINE_MEMORY: std::sync::atomic::AtomicUsize;
The leanest the process has ever been at an arming point: what the worker costs to exist, before any session ran.
pub const DEFAULT_MAX_RECURSION_DEPTH: usize = 1000;
Recommended maximum recursion depth if not otherwise specified.
pub const DEFAULT_MAX_SUSPENSIONS: usize = 1000;
Maximum suspensions a host services per session if not otherwise
specified: a backstop against a sandbox looping on host calls while
max_duration is paused.
pub const LARGE_RESULT_THRESHOLD: usize = 100_000;
Threshold in bytes above which check_large_result is called.
Operations that may produce results larger than this threshold (100KB) should call
check_large_result before performing the operation. This prevents DoS attacks
where operations like 2 ** 10_000_000 allocate huge amounts of memory before
the memory check can catch them.
pub static LIVE_MEMORY: std::sync::atomic::AtomicUsize;
Allocator-backed live bytes requested through the global allocator
pub const OOM_EXIT_CODE: i32 = 65;
Exit code a worker uses when it exceeded its memory limit or the allocator
refused an allocation, so the parent can report MemoryError instead of an
unclassifiable SIGABRT.
EX_DATAERR from BSD sysexits.h. See https://man.freebsd.org/cgi/man.cgi?query=sysexits.
pub enum ResourceError {
/// Maximum execution time exceeded.
Time { limit: std::time::Duration, elapsed: std::time::Duration },
/// Maximum memory usage exceeded.
Memory { limit: usize, used: usize },
/// Maximum recursion depth exceeded.
Recursion { limit: usize, depth: usize },
}
Error returned when a resource limit is exceeded during execution.
This allows the sandbox to enforce strict limits on execution time and memory usage.
All variants except Recursion are uncatchable inside the sandbox:
untrusted code must never intercept resource enforcement. Recursion
surfaces as a catchable RecursionError, matching CPython.
Implements: Clone, Debug, Display, Error, From<ResourceError>.
pub struct ResourceLimits {
/// Maximum execution time.
pub max_duration: Option<std::time::Duration>,
/// Maximum allocator-backed memory in bytes.
///
/// Requires the executable to install and arm `monty-alloc`.
pub max_memory: Option<usize>,
/// Run garbage collection every N GC-tracked allocations.
pub gc_interval: Option<usize>,
/// Maximum recursion depth (function call stack depth).
pub max_recursion_depth: usize,
/// Maximum suspensions the host may service (default
/// `DEFAULT_MAX_SUSPENSIONS`; always bounded, like recursion depth).
/// The interpreter only stores this limit; hosts must enforce it.
pub max_suspensions: usize,
}
Configuration for resource limits.
The time/memory/GC limits are optional — set to None to disable — but
recursion depth and the suspension budget are always bounded (defaults
DEFAULT_MAX_RECURSION_DEPTH and DEFAULT_MAX_SUSPENSIONS): unbounded
recursion would let sandboxed code overflow the native stack and abort the
process, and unbounded suspensions would let it loop on host calls. Use
ResourceLimits::default() for the recursion-only defaults, or build
custom limits with the builder pattern.
pub fn max_duration(self, limit: Duration) -> Self
Sets the maximum execution duration.
pub fn max_memory(self, limit: usize) -> Self
Sets allocator-backed maximum memory usage in bytes.
Requires the executable to install and arm monty-alloc; otherwise
the limit is silently not enforced.
pub fn gc_interval(self, interval: usize) -> Self
Sets the garbage collection interval (run GC every N GC-tracked allocations).
pub fn max_recursion_depth(self, limit: usize) -> Self
Sets the maximum recursion depth (function call stack depth).
pub fn max_suspensions(self, limit: usize) -> Self
Sets the host-enforced maximum number of suspensions.
Implements: Clone, Debug, Default, Deserialize<'de>, Serialize.
pub struct ResourceTracker { /* private fields */ }
A resource tracker that enforces configurable limits.
Checks allocator-backed memory usage and tracks execution time, returning errors when limits are exceeded. It also schedules garbage collection.
Uses Cell for mutable timing and recursion state behind shared references.
max_duration limits cumulative execution time: the clock runs only
while the VM is executing bytecode (between the outermost
on_execution_start/on_execution_stop pair) and is paused while
execution is suspended waiting on the host — external function calls,
OS callbacks — and between REPL feeds. The accumulated time is
serialized, so a deserialized session resumes its budget where it left
off rather than restarting from zero.
pub fn new(limits: ResourceLimits) -> Self
Creates a new ResourceTracker with the given limits.
The execution-time clock starts at zero and only runs while the VM
executes, so the tracker can be created any amount of time before
the first run without consuming the duration budget. A configured
max_memory requires monty-alloc installed as the global allocator
and armed via its set_limit; otherwise it is silently not enforced.
pub fn elapsed(&self) -> Duration
Returns the cumulative execution time: bytecode-execution wall time accumulated across runs/feeds, excluding time suspended on the host or idle between feeds. Includes the in-progress window if the VM is currently executing.
pub fn max_duration(&self) -> Option<Duration>
Returns the configured maximum cumulative execution time, if any.
pub fn max_memory(&self) -> Option<usize>
Returns the configured memory budget, if any. Hosts that bound a worker process from outside the interpreter size that bound from this.
pub fn max_suspensions(&self) -> usize
Returns the host-enforced suspension budget (default
DEFAULT_MAX_SUSPENSIONS; never unlimited).
pub fn has_memory_time_limit(&self) -> bool
Returns whether the VM has a memory or time limit configured.
pub fn set_max_duration(&mut self, duration: Duration)
Sets the maximum execution duration as a fresh budget from now, resetting the accumulated execution time to zero.
This lets a host enforce a different (typically shorter) time limit
for a resumed phase — e.g. allowing a long build phase, then giving
repr() of the result only a few milliseconds. Time spent suspended
in the host never counts toward the budget either way.
pub fn check_allocation(&self, additional: usize) -> Result<(), ResourceError>
Checks whether one up-front allocation fits the memory budget.
Use this before reserving a buffer that could cross both the soft and hard allocator limits before execution reaches another checkpoint.
pub fn check_memory_time(&self) -> Result<(), ResourceError>
Called periodically to check allocator-backed memory and time limits.
Returns Ok(()) while configured limits are respected, or the relevant
resource error once either limit is exceeded.
Takes &self rather than &mut self because checking elapsed time is a
read-only operation. This allows time checks in contexts that only have
an immutable heap reference, such as py_repr_fmt.
pub fn check_time(&self) -> Result<(), ResourceError>
Called periodically to check the time limit. Elapsed execution time is monotonic, so once the budget is exceeded every later call fails too.
pub const LOOP_CHECK_INTERVAL: usize = 64;
Items processed between full checks in amortized per-item Rust loops
(see check_time_every). A limit can be
overshot by up to this many items’ work before the next check — an
accepted trade for cheap loops; the process-level hard limits backstop
pathological cases.
pub fn check_time_every(&self, i: usize) -> Result<(), ResourceError>
Amortized per-item time check for Rust-side loops: a full clock read
once per LOOP_CHECK_INTERVAL calls,
free otherwise. Key i on the loop’s index or a monotonically
increasing counter. Fires at the end of each block (i % N == N-1)
so loops shorter than the interval pay no clock read at all — the VM
dispatch checkpoint covers cadence between short calls.
pub fn check_memory_time_every(&self, i: usize) -> Result<(), ResourceError>
Amortized per-item memory + time check; the memory-probing sibling of
check_time_every, for loops that allocate
per item. Between full checks the allocator’s hard limit still bounds
runaway growth.
pub fn check_recursion_depth(&self, current_depth: usize) -> Result<(), ResourceError>
Called before pushing a new call frame to check recursion depth.
Returns Ok(()) if within recursion limit, or Err(ResourceError::Recursion)
if the limit would be exceeded. current_depth is the call stack depth
before the new frame is pushed.
pub fn check_large_result(&self, estimated_bytes: usize) -> Result<(), ResourceError>
Called before operations that may produce large results (>100KB).
This allows pre-emptive rejection of operations like 2 ** 10_000_000
before the memory is actually allocated. The check only happens for
estimated result sizes above LARGE_RESULT_THRESHOLD to avoid overhead
on small operations.
pub fn gc_interval(&self) -> Option<usize>
Returns the configured garbage collection interval, in GC-tracked allocations.
The cycle collector runs at most once per gc_interval GC-tracked
allocations, and additionally short-circuits when no cycle candidates
are pending — so programs that never form cycles pay no collector
cost regardless of their allocation rate. None tells the heap to use
its built-in default scheduling threshold.
pub fn on_execution_start(&self)
Called when the VM enters its execution loop from a host boundary
(VM::run_external), starting one execution window.
Paired with on_execution_stop and never
nested — VM-internal re-entry (task switches, host-initiated function
evaluation) uses the raw run loop, so its time falls inside the
enclosing window. The execution-time clock runs between the pair; it is
not running while execution is suspended waiting on the host
(external function calls) or between feeds.
pub fn on_execution_stop(&self)
Called when the VM leaves its execution loop — on completion, error,
or suspension at an external call. See on_execution_start.
Implements: Debug, Default, Deserialize<'de>, Serialize.
pub enum ExtFunctionResult {
/// Continues execution with the return value from the external function.
Return(MontyObject),
/// Continues execution with the exception raised by the external function.
Error(MontyException),
/// Pending future — the external function is a coroutine.
///
/// The `u32` is the `call_id` from the `FunctionCall` that created this
/// snapshot. It is used to track the pending future so it can be resolved
/// later via `ResolveFutures::resume()`.
Future(u32),
/// The function was not found, should result in a `NameError` exception.
NotFound(String),
}
Return value or exception from an external function.
Implements: Debug, From<MontyException>, From<MontyObject>.
pub enum NameLookupResult {
/// The name resolves to this value.
Value(MontyObject),
/// The name is undefined — the VM raises `NameError` / `AttributeError`.
Undefined,
/// Resolving the name raised this exception on the host; the VM raises
/// it where the lookup suspended, like a failed external call.
Error(MontyException),
}
Result of a name lookup from the host.
When the VM encounters an unresolved name (or a lazy attribute on a host-backed object), the host provides one of these:
Value(obj): The name resolves to this value (a plain name is cached in its namespace slot; an attribute is re-consulted on every access).Undefined: The name does not exist —NameErrorfor a plain name,AttributeErrorfor an attribute.Error(exc): Resolving it raised on the host — the exception is raised inside the sandbox, sohasattr()/getattr()defaults do not apply.
Implements: Debug, From<MontyException>, From<MontyObject>, From<Option<MontyObject>>.
pub enum AssertMessageAnnotations {
/// Disable introspection; bare asserts use CPython's empty message.
Off,
/// Retain at most this many UTF-8 bytes per operand before any `…` suffix.
/// Non-zero because `0` encodes `Off` on the wire.
MaxBytes(std::num::NonZeroU32),
}
Controls the pytest-style introspected assert failure messages of
CompileOptions::assert_message_annotations.
The choice is baked in at compile time (whether the introspecting opcodes are emitted) but the truncation limit is applied at runtime, so it also travels with serialized sessions.
pub const DEFAULT_MAX_BYTES: NonZeroU32 = _;
Operand-repr truncation used by Default and From<bool>.
pub fn enabled(self) -> bool
Whether the compiler should emit introspecting assert opcodes.
pub fn max_bytes(self) -> u32
Returns the wire value: 0 when disabled, otherwise the UTF-8 byte cap.
pub fn from_max_bytes(value: u32) -> Self
Decodes the wire value: 0 is off and any other value is the byte cap.
Implements: Clone, Copy, Debug, Default, Deserialize<'de>, Eq, From<bool>, PartialEq, Serialize, StructuralPartialEq.
pub struct CompileOptions {
/// Give failed `assert` statements pytest-style introspected messages,
/// deliberately diverging from CPython; see `limitations/assert.md`.
/// On by default with a 120-byte operand-repr truncation.
pub assert_message_annotations: AssertMessageAnnotations,
}
Options controlling how Monty behavior diverges from plain CPython.
Consumed when code is compiled: a MontyRun bakes the choices into the
program at construction, while a MontyRepl stores them so every snippet
fed to the session compiles the same way.
Implements: Clone, Copy, Debug, Default, Deserialize<'de>, Serialize.
pub struct TypeCheckState {
/// User-provided stubs plus every snippet that has completed successfully.
pub committed_stubs: String,
/// The in-flight snippet; committed on success, discarded on error.
pub pending_snippet: Option<String>,
/// How diagnostics are rendered by whoever runs the type checker.
pub config: TypeCheckingConfig,
}
Per-session type-check state: successfully committed snippets accumulate as stubs so later snippets can reference names defined by earlier ones.
Implements: Clone, Debug, Deserialize<'de>, Serialize.
pub struct TypeCheckingConfig {
/// Output format.
pub format: TypeCheckingFormat,
/// Whether to include ANSI colour escapes. Only `Full` and `Concise`
/// render any colour; the machine-readable formats ignore it.
pub color: bool,
}
How a type check renders whatever diagnostics it finds.
Implements: Clone, Copy, Debug, Default, Deserialize<'de>, Eq, PartialEq, Serialize, StructuralPartialEq.
pub enum TypeCheckingFormat {
/// Human-readable diagnostics with a source snippet and carets.
Full,
/// One `path:line:col: severity[rule] message` line per diagnostic.
Concise,
/// Azure Pipelines logging commands.
Azure,
/// A JSON array of diagnostic objects.
Json,
/// One JSON diagnostic object per line.
JsonLines,
/// Reviewdog diagnostic JSON.
Rdjson,
/// Pylint-compatible output.
Pylint,
/// GitLab Code Quality report JSON.
Gitlab,
/// GitHub Actions workflow commands.
Github,
}
How type-check diagnostics are rendered into text.
Mirrors ty’s DiagnosticFormat. Rendering happens wherever the type checker
runs (inside the worker for pool sessions), because ty’s structured
diagnostics borrow the salsa database and cannot cross a process boundary —
so the format has to be chosen before the check, not after it.
Serialized into session dumps by discriminant, so new variants must be
appended — inserting one shifts every later variant and silently rewrites
older dumps’ format (see DUMP_VERSION in monty).
pub fn from_name(name: &str) -> Result<Self, String>
Parses a format name, reporting the valid names on failure.
Bindings take the format as a string, so the error has to be good enough to show a user who guessed wrong.
pub fn names() -> String
Comma-separated list of the accepted format names.
Implements: Clone, Copy, Debug, Default, Deserialize<'de>, Display, Eq, FromStr, PartialEq, Serialize, StructuralPartialEq, TryFrom<&str>, VariantNames.
pub struct MontyUuid(/* private */);
A 16-byte UUID identifying a host or sandbox class/instance across the sandbox boundary.
pub const fn from_bytes(bytes: [u8; 16]) -> Self
Wraps raw bytes as-is; used when the bytes are already a valid uuid.
pub const fn from_u128(v: u128) -> Self
Builds a deterministic id from an integer — for tests and fixtures that must be reproducible; never use for real identity.
pub const fn from_random_bytes(bytes: [u8; 16]) -> Self
Stamps the uuid4 version and RFC 4122 variant bits over caller-supplied random bytes, so any entropy source yields a well-formed uuid4.
pub const fn as_bytes(&self) -> &[u8; 16]
Returns the raw bytes (big-endian field order, per RFC 4122).
pub fn try_from_slice(bytes: &[u8]) -> Option<Self>
Parses exactly 16 bytes; None for any other length. This is the
wire-decode entry point, so it must never panic.
pub fn parse(s: &str) -> Option<Self>
Parses the canonical hyphenated form (8-4-4-4-12 hex digits), any
case; None on any deviation. Used by the JS surfaces, which carry
uuids as strings.
Implements: Clone, Copy, Debug, Deserialize<'de>, Display, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize, StructuralPartialEq.