create seamless slices when getting a substring

This commit is contained in:
Brendan Hansknecht 2023-12-05 22:46:43 -08:00
parent 9889984dd4
commit 087ca115c9
No known key found for this signature in database
GPG key ID: A199D0660F95F948
3 changed files with 29 additions and 4 deletions

View file

@ -1498,8 +1498,33 @@ pub fn getCapacity(string: RocStr) callconv(.C) usize {
} }
pub fn substringUnsafe(string: RocStr, start: usize, length: usize) callconv(.C) RocStr { pub fn substringUnsafe(string: RocStr, start: usize, length: usize) callconv(.C) RocStr {
const slice = string.asSlice()[start .. start + length]; if (string.isSmallStr()) {
return RocStr.fromSlice(slice); if (start == 0) {
var output = string;
output.setLen(length);
return output;
}
const slice = string.asSlice()[start .. start + length];
return RocStr.fromSlice(slice);
}
if (string.str_bytes) |source_ptr| {
if (start == 0 and string.isUnique()) {
var output = string;
output.setLen(length);
return output;
} else {
const str_ref_ptr = (@intFromPtr(source_ptr) >> 1);
const slice_ref_ptr = string.str_capacity;
const slice_mask = string.seamlessSliceMask();
const ref_ptr = (str_ref_ptr & ~slice_mask) | (slice_ref_ptr & slice_mask);
return RocStr{
.str_bytes = source_ptr + start,
.str_len = length | SEAMLESS_SLICE_BIT,
.str_capacity = ref_ptr,
};
}
}
return RocStr.empty();
} }
pub fn getUnsafe(string: RocStr, index: usize) callconv(.C) u8 { pub fn getUnsafe(string: RocStr, index: usize) callconv(.C) u8 {

View file

@ -1540,7 +1540,7 @@ fn low_level_no_rc(lowlevel: &LowLevel) -> RC {
StrGetUnsafe | ListGetUnsafe => RC::NoRc, StrGetUnsafe | ListGetUnsafe => RC::NoRc,
ListConcat => RC::Rc, ListConcat => RC::Rc,
StrConcat => RC::Rc, StrConcat => RC::Rc,
StrSubstringUnsafe => RC::NoRc, StrSubstringUnsafe => RC::Rc,
StrReserve => RC::Rc, StrReserve => RC::Rc,
StrAppendScalar => RC::Rc, StrAppendScalar => RC::Rc,
StrGetScalarUnsafe => RC::NoRc, StrGetScalarUnsafe => RC::NoRc,

View file

@ -1292,7 +1292,7 @@ fn lowlevel_borrow_signature(arena: &Bump, op: LowLevel) -> &[Ownership] {
StrGetUnsafe | ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrGetUnsafe | ListGetUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]),
ListConcat => arena.alloc_slice_copy(&[owned, owned]), ListConcat => arena.alloc_slice_copy(&[owned, owned]),
StrConcat => arena.alloc_slice_copy(&[owned, borrowed]), StrConcat => arena.alloc_slice_copy(&[owned, borrowed]),
StrSubstringUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant, irrelevant]), StrSubstringUnsafe => arena.alloc_slice_copy(&[owned, irrelevant, irrelevant]),
StrReserve => arena.alloc_slice_copy(&[owned, irrelevant]), StrReserve => arena.alloc_slice_copy(&[owned, irrelevant]),
StrAppendScalar => arena.alloc_slice_copy(&[owned, irrelevant]), StrAppendScalar => arena.alloc_slice_copy(&[owned, irrelevant]),
StrGetScalarUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]), StrGetScalarUnsafe => arena.alloc_slice_copy(&[borrowed, irrelevant]),