This repository has been archived on 2025-08-04. You can view files and clone it, but cannot push or open issues or pull requests.
rhaj/_archive/rhai_engine/rhaibook/rust/immutable-string.md
2025-04-04 08:28:07 +02:00

77 lines
3.0 KiB
Markdown

The `ImmutableString` Type
==========================
{{#include ../links.md}}
~~~admonish question.side "Why `SmartString`?"
[`SmartString`] is used because many strings in scripts are short (fewer than 24 ASCII characters).
~~~
All [strings] in Rhai are implemented as `ImmutableString`, which is an alias to
`Rc<SmartString>` (or `Arc<SmartString>` under the [`sync`] feature).
An `ImmutableString` is immutable (i.e. never changes) and therefore can be shared among many users.
Cloning an `ImmutableString` is cheap since it only copies an immutable reference.
Modifying an `ImmutableString` causes it first to be cloned, and then the modification made to the copy.
Therefore, direct string modifications are expensive.
Avoid `String` Parameters
-------------------------
`ImmutableString` should be used in place of `String` for function parameters because using `String`
is very inefficient (the argument is cloned during every function call).
A alternative is to use `&str` which de-sugars to `ImmutableString`.
A function with the first parameter being `&mut String` does not match a string argument passed to it,
which has type `ImmutableString`. In fact, `&mut String` is treated as an opaque [custom type].
```rust
fn slow(s: String) -> i64 { ... } // string is cloned each call
fn fast1(s: ImmutableString) -> i64 { ... } // cloning 'ImmutableString' is cheap
fn fast2(s: &str) -> i64 { ... } // de-sugars to above
fn bad(s: &mut String) { ... } // '&mut String' will not match string values
```
Differences from Rust Strings
-----------------------------
Internally Rhai strings are stored as UTF-8 just like Rust (they _are_ Rust `String`s!),
but nevertheless there are major differences.
In Rhai a [string] is semantically the same as an array of Unicode characters and can be directly
indexed (unlike Rust).
This is similar to most other languages (e.g. JavaScript, C#) where strings are stored internally
not as UTF-8 but as arrays of UCS-16 or UCS-32.
Individual characters within a Rhai string can also be replaced just as if the string is an array of
Unicode characters.
In Rhai, there are also no separate concepts of `String` and `&str` (a string slice) as in Rust.
```admonish warning "Performance considerations"
Although Rhai exposes a [string] as a simple array of [characters] which can be directly indexed to
get at a particular [character], such convenient syntax is an _illusion_.
Internally the [string] is still stored in UTF-8 (native Rust `String`s).
All indexing operations actually require walking through the entire UTF-8 string to find the offset
of the particular [character] position, and therefore is _much_ slower than the simple array
indexing for other scripting languages.
This implementation detail is hidden from the user but has a performance implication.
Avoid large scale [character]-based processing of [strings]; instead, build an actual [array] of
[characters] (via the `split()` method) which can then be manipulated efficiently.
```