Motivation
Andy C++ strings use Rc<RefCell> and expose character-based sequence semantics. Operations such as length, bounds checking, negative-index resolution, indexing, and slicing can scan UTF-8 text repeatedly. Most Advent of Code input is ASCII, where byte offsets and character offsets are identical.
Proposal
Introduce a wrapper with a private String and cached character length:
struct AndyCppString {
inner: String,
char_len: usize,
}
A separate ASCII flag is unnecessary while the inner value remains valid UTF-8: the string is ASCII exactly when char_len equals inner.len().
Store Rc<RefCell> in Object::String. Expose immutable text through as_str or AsRef, but do not expose &mut String, DerefMut, or AsMut. All mutation must go through wrapper methods so char_len cannot drift from the contents.
Mutation rules
- Constructors calculate char_len once, using byte length directly for ASCII input.
- Concatenation and append add the cached lengths.
- Character-range replacement subtracts the removed character count and adds the replacement length.
- Reversal preserves the length.
- Unicode transformations that may change the number of scalar values construct a new wrapper or recount after mutation.
- Debug builds assert that char_len matches inner.chars().count() after mutations.
The native-function conversion machinery currently permits functions such as append and reverse to receive &mut String. Migrate those functions to the wrapper or another invariant-preserving API.
Expected impact
- O(1) string length and negative-index bounds resolution.
- O(1) ASCII element access and byte-range slicing after bounds checking.
- Non-ASCII access still scans for the requested UTF-8 boundary, but avoids a separate full length scan.
- Existing UTF-8 and character-index semantics remain unchanged.
Acceptance criteria
- Object::String uses the wrapper throughout the VM and standard library.
- No public mutable access to the inner String can bypass cache maintenance.
- Existing string behavior tests pass, including multibyte indexing, slicing, assignment, iteration, and native string functions.
- New tests exercise cache maintenance after every supported mutation category.
- Benchmarks compare repeated ASCII indexing and length calls before and after the change.
Non-goals
This issue does not change strings to arbitrary byte sequences or change indexing from Unicode scalar values to bytes.
AI disclosure
This issue was drafted with OpenAI Codex assistance.
Motivation
Andy C++ strings use Rc<RefCell> and expose character-based sequence semantics. Operations such as length, bounds checking, negative-index resolution, indexing, and slicing can scan UTF-8 text repeatedly. Most Advent of Code input is ASCII, where byte offsets and character offsets are identical.
Proposal
Introduce a wrapper with a private String and cached character length:
A separate ASCII flag is unnecessary while the inner value remains valid UTF-8: the string is ASCII exactly when char_len equals inner.len().
Store Rc<RefCell> in Object::String. Expose immutable text through as_str or AsRef, but do not expose &mut String, DerefMut, or AsMut. All mutation must go through wrapper methods so char_len cannot drift from the contents.
Mutation rules
The native-function conversion machinery currently permits functions such as append and reverse to receive &mut String. Migrate those functions to the wrapper or another invariant-preserving API.
Expected impact
Acceptance criteria
Non-goals
This issue does not change strings to arbitrary byte sequences or change indexing from Unicode scalar values to bytes.
AI disclosure
This issue was drafted with OpenAI Codex assistance.