Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .agents/languages/cpp.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ Load this file when changing `cpp/`, Cython build plumbing, or C++ xlang behavio
- Do not redesign alias-based or low-level public type shapes to add convenience methods unless the user explicitly asks for that API change.
- For cross-language feature ports, match protocol behavior but use idiomatic C++ ownership and layering instead of mirroring Java structure literally.
- Compatible scalar, list-array, and binary/uint8-array adaptations are immediate-field-only. Recursive matched-field comparison for collection elements, array elements, map keys, and map values must require exact nullability, ref tracking, generic arity, and type shape except documented user-type family normalization.
- Root deserialization container budgets are owned by `ReadContext` and initialized by the root
`Fory::deserialize` overload. Keep `max_container_memory_bytes` as `-1 / auto` or a positive
explicit limit; known byte roots use `inputBytes * 8 + 64 KiB`, while stream roots use fixed
`128 MiB`. Reserve estimated container-owned memory before allocation but preserve existing
byte-availability checks and their non-empty metadata ordering. Skip only dedicated string,
binary, primitive vector, and primitive dense-array owners; general `std::vector<T>` for
non-primitive `T` is inline container storage and must be charged.

## Key Paths

Expand Down
2 changes: 2 additions & 0 deletions .agents/languages/csharp.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Load this file when changing `csharp/` or C# xlang behavior.
- Generated C# gRPC service companions are compiler-owned files that depend on application-provided gRPC packages, not `csharp/src/Fory`. Keep gRPC package references out of the Fory runtime package.
- C# generated schema modules are source-file owners. Service companions must use that module's `ThreadSafeFory` and must not introduce namespace-owned aliases or duplicate serializer registration paths.
- Compatible scalar, list-array, and binary/uint8-array adaptations are immediate-field-only. Recursive matched-field comparison for collection elements, array elements, map keys, and map values must require exact nullability, ref tracking, generic arity, and type shape except documented user-type family normalization.
- Root deserialization container memory budget state belongs to `ReadContext`. C# public roots are memory-backed today, so auto uses known input length; generated serializers may call `ReadContext`'s generated-code reservation helpers, but should not expose or depend on serializer helper classes such as `CollectionCodec`.
- For C# container budget formulas, distinguish inline value storage from reference storage: use cheap value-type size for `List<T>`/`T[]` value paths and the 4-byte reference fallback for reference paths. Dedicated string, binary, and primitive dense-array serializers stay skipped and rely on byte availability checks.
- When extending C# tests from Java references, prioritize xlang spec behavior and the public C# contract before adding complex Java-specific parity cases.

## Commands
Expand Down
1 change: 1 addition & 0 deletions .agents/languages/dart.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Load this file when changing `dart/`.
- Keep root numeric wrapper defaults separate from generated field metadata. Root wrapper resolution belongs in the builtin resolver, while annotations and generated metadata choose fixed, tagged, or declared-field encodings.
- Dart 64-bit carriers are optimized for each platform. Do not replace native extension-type wrappers with allocation-heavy classes or route web/native hot paths through `BigInt` unless the user approves a representation change.
- In `Buffer`, cursor, serializer, and generated-code hot paths, prefer direct byte/local integer operations and conditional import/export files over callbacks, records, holder objects, wrapper round-trips, or runtime platform branches.
- Root deserialization container memory budgets are owned by `ReadContext`; `maxContainerMemoryBytes` defaults to `-1 / auto`, positive explicit values win, and Dart auto uses `buffer.readableBytes * 8 + 64 KiB` because roots are memory-backed. Charge Dart lists, sets, maps, object/reference arrays, compatible list-to-array inline storage, and compatible array-to-list materialization before allocation. Skip only dedicated string, binary, `BoolList`, and typed-array dense owner paths with byte checks. Do not add stream bytes-read accounting, per-element accounting, or extra hot-path allocations for this budget.
- Do not add parallel header-low/header-high slot caches or multi-slot recent caches in TypeMeta hot paths to chase benchmark gaps. Header-cache hits must use the concrete checked cache owner directly; if a hit hint is needed, cache one TypeInfo/TypeMeta object and compare the validated header identity on that object, not separate low/high header fields or benchmark-pattern state.
- If Dart TypeMeta cache ownership changes, keep the invariant in a source comment near the hit path: a checked metadata-cache hit skips the body and must not grow low-bit sentinels, accepted-header fields, parallel header slots, or benchmark-pattern state.
- Dart expected-type TypeDef reads should compare the expected `TypeInfo` object's cached local TypeDef header before consulting the parsed-metadata map. A match is a direct local-schema hit: skip the remote body, add the expected type to the per-read shared type table, and do not publish to `ParsedTypeMetaCache`, record a remote schema version, or parse/hash the body.
Expand Down
8 changes: 8 additions & 0 deletions .agents/languages/go.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ Load this file when changing `go/fory/` or Go xlang behavior.
- Run Go commands from within `go/fory/`.
- Changes under `go/` must pass formatting and tests.
- The Go implementation focuses on reflection-based and codegen-based serialization.
- Root deserialization container memory budgets are owned by `ReadContext`.
`WithMaxContainerMemoryBytes` defaults to `-1 / auto`; byte-slice roots use
`inputBytes * 8 + 64 KiB`, and `DeserializeFromReader`/`DeserializeFromStream`
use fixed `128 MiB`. Charge Go slices, maps, map-backed sets, LIST-encoded
inline/value slices, and generated container reads before allocation. Fixed
arrays are caller-owned and normally not charged; `arrayDynSerializer` charges
its temporary slice. Skip only dedicated string, binary, BufferObject,
primitive ARRAY slice, and primitive array owners with byte checks.
- Set `FORY_PANIC_ON_ERROR=1` when debugging a failing Go test so you get the full call stack.
- Do not set `FORY_PANIC_ON_ERROR=1` when running the full Go test suite, because some tests assert on error contents.

Expand Down
9 changes: 9 additions & 0 deletions .agents/languages/java.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,15 @@ Load this file when changing anything under `java/` or when Java drives a cross-
values; use qualified names only when a real name conflict requires it.
- If you run temporary tests with `java -cp`, run `mvn -T16 install -DskipTests` first so local Fory jars are current.
- `WriteContext`, `ReadContext`, and `CopyContext` must stay explicit. Do not reintroduce `ThreadLocal` or ambient runtime-context patterns.
- Java root deserialization container memory budgeting belongs to `ReadContext`
and is initialized by `Fory` root APIs. Public config is
`maxContainerMemoryBytes` with `-1` auto, positive explicit override,
known-length auto `inputBytes * 8 + 64 KiB`, and stream/unknown auto
`128 MiB`. Collection/map/object-array serializers should charge estimated
container-owned memory before allocation while preserving existing
`checkReadableBytes` guards before backing allocation or capacity
reservation. Do not add nested serializer-path `try/finally`, per-element
work, or dynamic stream bytes-read accounting for this budget.
- Generated serializers must not retain runtime context fields. `Fory` should stay a root-operation facade rather than accumulating serializer or convenience state.
- When the serializer class and constructor shape are known at the call site, prefer direct constructor lambdas or direct instantiation over reflective `Serializers.newSerializer(...)`.
- For GraalVM, use `fory codegen` to generate serializers when building native images. Do not add reflection configuration except for JDK `proxy`.
Expand Down
7 changes: 7 additions & 0 deletions .agents/languages/javascript.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,13 @@ Load this file when changing `javascript/`.
- Runtime value carriers such as decimal or reduced-precision numeric types belong under the core `types/` ownership boundary, with imports, exports, and codegen externals updated together.
- Keep `TypeInfo` as schema metadata. Compatibility-sensitive decisions belong on `TypeResolver` or explicit operations, not as retained resolver state on metadata objects.
- Normalize optional boolean config values at config construction; do not carry `null` through runtime paths when it means `false`.
- JavaScript root deserialization container memory budgeting belongs to `ReadContext`.
`maxContainerMemoryBytes` uses `-1` auto, positive explicit limits, and known
`Uint8Array` root length as `inputBytes * 8 + 64 KiB`. Generated and dynamic
list/set/map readers must reserve before allocation while preserving existing
byte checks. Keep dedicated string, binary, and dense typed-array owners out of
this budget; compatible list-to-typed-array reads must charge typed inline
storage.
- Regenerated compatible read serializers are remote-schema-specific. After classification marks a field as direct, compatible scalar, or skip, generated JavaScript should emit straight-line remote-field-order code. Do not add an outer matched-id switch unless the current regenerated shape cannot preserve those semantics.
- Compatible scalar codegen must decide the exact remote/local scalar pair before emitting source. Generate the concrete `reader.readXxx()` call plus inline trivial conversions such as boolean-to-string or numeric widening, and keep helpers only for semantic validation such as range checks, exactness checks, decimal parsing/formatting, and string-to-bool. Do not call a generic hot-path converter that redispatches on `remoteTypeId`, `localTypeId`, field descriptors, or field names.
- Compatible scalar conversion is immediate-field-only. Recursive schema comparison for collection elements, array elements, map keys, and map values must reject scalar mismatches instead of applying the top-level scalar conversion matrix.
Expand Down
6 changes: 6 additions & 0 deletions .agents/languages/python.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ Load this file when changing `python/`, Cython serialization, or Python xlang be
- Cython mode owns the hot runtime path. Do not duplicate core runtime types between Python and Cython, tunnel Python facade methods into hidden Cython internals, or keep dead shims unless the user explicitly needs a compatibility module path.
- Use explicit Cython fields and methods for fixed hot-path shapes. Avoid `__getattr__`, generic `object` fields, public bridge internals, or `Fory` backreferences where ownership can stay explicit.
- Keep Python and Cython context/ref-tracking branch conditions and stack mutations semantically aligned unless a documented intentional difference exists.
- Root deserialization container memory budgets are owned by pure-Python and Cython `ReadContext`.
Keep `max_container_memory_bytes` public on `pyfory.Fory`/`Config`; `-1` uses known-length
`inputBytes * 8 + 64 KiB` or fixed `128 MiB` for stream roots. Reserve fixed container cost plus
reference slots for list/tuple/set, map object/table/entry estimates for dict, and object-dtype
ndarray item storage. Keep string, bytes, `array.array`, primitive dense array, and primitive
ndarray owners skipped, and preserve byte-availability checks after budget reservation.
- Public value constructors should accept normal Python values. Raw-bit, raw-buffer, and memoryview entry points should be explicit low-level APIs, and packed carriers should expose the buffer protocol from the actual storage owner when appropriate.
- When debugging runtime or benchmark behavior, install the local package into the exact interpreter under test instead of relying on mixed `PYTHONPATH` state.
- For wheel or extension pipeline changes, derive extension-module paths from current build targets, packaging config, or wheel payload discovery rather than historical module names.
Expand Down
10 changes: 10 additions & 0 deletions .agents/languages/rust.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,16 @@ Load this file when changing `rust/` or Rust xlang behavior.
- If breakage is explicitly acceptable during a Rust module refactor, rewire macros, tests, and sibling crates directly to the new boundaries instead of adding compatibility re-exports.
- For panic-safety in hot paths, preserve TLS context reuse. Add scoped guards or owned fallbacks rather than per-call context allocation, and reset reused contexts at entry and successful exit.
- Compatible scalar, list-array, and binary/uint8-array adaptations are immediate-field-only. Keep recursive matched-field shape classification owned by `fory-core/src/meta/type_meta.rs`; collection elements, array elements, map keys, and map values must require exact nullability, ref tracking, generic arity, and type shape except documented user-type family normalization.
- Root deserialization container memory budget state belongs to `ReadContext` and is initialized by
the root `Fory` read methods before the header is consumed. Rust roots are byte-slice/`Reader`
backed, so auto budget uses `inputBytes * 8 + 64 KiB`; do not add dynamic bytes-read accounting.
- Rust `Vec<T>` stores inline element storage, so general LIST paths charge fixed `Vec` cost plus
`len * size_of::<T>()`, including `Vec<String>` and `Vec<struct>`. Dedicated primitive dense
ARRAY `Vec<T>` readers, strings, binary, and primitive fixed-array owners stay skipped and keep
their byte checks.
- Direct `Serializer` collection/map paths and derive `Codec` collection/map paths are separate
allocation owners. Keep reservations in both before `Vec::with_capacity`,
`HashMap::with_capacity`, or collection materialization; charge zero-size containers.

## Key Paths

Expand Down
2 changes: 2 additions & 0 deletions .agents/languages/swift.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ Load this file when changing `swift/` or Swift xlang behavior.
- Preserve distinct temporal semantics. Timestamp values and day-only local dates should have protocol-accurate helper names and no stale aliases after a refactor.
- When temporal or public-type refactors touch generated Swift code, sweep message fields, union payloads, macros, xlang harnesses, and integration fixtures together.
- Compatible scalar, list-array, and binary/uint8-array adaptations are immediate-field-only. Recursive matched-field comparison for collection elements, array elements, map keys, and map values must require exact nullability, ref tracking, generic arity, and type shape except documented user-type family normalization.
- Root deserialization container memory budget state belongs to `ReadContext`. Swift public roots are `Data` and `ByteBuffer`, so auto uses known root bytes; do not add stream bytes-read accounting or serializer-local budget state.
- For Swift container budget formulas, distinguish inline/value storage from reference storage: use `MemoryLayout<T>.stride` for value arrays/lists/maps and the 4-byte reference fallback for `Serializer.isRefType` / `FieldCodec.isRefType` paths. Dedicated `String`, `Data`/binary, and primitive packed-array owners stay skipped, except compatible packed-array-to-list reads must charge the target list materialization before allocation.

## Commands

Expand Down
Loading
Loading