Reading bytes(memcpyout of a string, memmem, scanning): replace addr s[i]/ unsafeAddr s[i]with readRawData(s, i).
Writing bytes in bulk(memcpy/freadinto a string): replace setLen+ addr s[oldLen]with beginStore(s, newLen, start)followed by endStore(s). beginStorealready sets the length and does the copy-on-write / unique-ownership dance, so an explicit prepareMutationis no longer needed.
A pointer that must outlive the current scope(e.g. a cursor stored next to its buffer): use readRawDataStable, which forces the string onto the heap so the payload address is stable.
Single-element writes[i] = cstill works unchanged — the compiler lowers it to nimStrPutV3, which handles COW internally. You no longer need prepareMutation(s)before an indexed assignment.
# beforeprepareMutation(buffer)# COW literal guard under ARCresult=s.readData(addrbuffer[slice.a],count)# afterresult=s.readData(beginStore(buffer,slice.b+1-slice.a,slice.a),count)endStore(buffer)
cstringconversions
Converting string → cstringstill works, but the C string is only valid as long as the source string is alive and unmodified.
If you need a stable, NUL-terminated buffer to hand to C, keep the owning stringalive and derive the pointer from it (via readRawDataStable/ the normal cstringconversion) rather than caching the pointer past a move.
Migration checklist
[ ] Grep your code for addr s[, unsafeAddr s[, addr(...data[, and any cached pointer/cstringinto a string.
[ ] Replace read accesses with readRawData(or readRawDataStableif the pointer escapes the current scope / must survive a move).
[ ] Replace setLen+ raw write with beginStore/ endStore.
[ ] Drop now-redundant prepareMutationcalls before indexed writes and beginStore.
[ ] Don't assume addr s[0]is stable across add, reassignment, or passing the string by value.
[ ] Build once with --strings:ssoand once without to confirm the code compiles and behaves identically under both.
Because the helper API has identical signatures on every string backend, code written this way keeps working under refc/ARC/ORC without SSO — you can port incrementally and flip --strings:ssoon when ready.
Once again, in order to avoid confusions:
Updating your code is not required, but beneficial. The same API works for all `mm` switches and is also offered by Nimony/Nim 3.