Skip to content
Merged
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
4 changes: 0 additions & 4 deletions quest/m3/ts-unsafe.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,6 @@ none of its own `unsafe`.
`set_len` is refused, and a write past the length fails loudly at run time, since the
JS array would grow by it. The spare slots need to live outside the array's length
until `set_len` takes them.
- `offset_from` between byte pointers into two views of one buffer, such as a slice's
`as_mut_ptr` and its `iter_mut`'s first element: each is an `rt.AtIndex` into its own
`Uint8Array`, so it fails loudly at run time where Rust measures the distance. Comparing
by buffer and byte offset closes it.
- `UnsafeCell::raw_get`, `from_mut`, and `replace`, refused with their span: none is in
moq's census at the pin.
- A byte pointer moved past its own `Uint8Array` view into the rest of the buffer, such as
Expand Down
17 changes: 15 additions & 2 deletions ts/fixtures/lang/expected/elements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,8 @@ export function inline(data: rt.ByteSlice, out: rt.ByteVec): void {
* the array of one Rust treats it as, and into a mutable part of an array, measured from
* the array, the pointer an empty slice keeps, within a shared part, which JS copies,
* a `&mut` into that part, memory nothing wrote copied, null and dangling pointers moved by
* address, kept by empty raw slices, and cast from pointers to arrays, and the crate's
* functions named as std's.
* address, kept by empty raw slices, and cast from pointers to arrays, the crate's
* functions named as std's, and byte pointers into one buffer through its views.
*/
export function edges(data: rt.ByteSlice, out: rt.ByteVec): void {
let _200!: rt.Result<[rt.u32, rt.u32], rt.u8>;
Expand Down Expand Up @@ -318,6 +318,19 @@ export function edges(data: rt.ByteSlice, out: rt.ByteVec): void {
rt.byteVecPush(out, rt.ptrWrappingAdd(rt.byteSliceAsPtr(rt.NULL), n as rt.usize, 1, 1) === rt.NULL ? 1 : 0);
rt.byteVecPush(out, rt.ptrWrappingAdd(rt.sliceAsPtr(rt.DANGLING), -1, 2, 2) === rt.NULL ? 1 : 0);
}
const bytes2: Uint8Array = Uint8Array.of(option_unwrapOr$0r2bmpr(rt.byteSliceFirst(data), 0), 1, 2, 3, 4, 5);
const s: rt.ByteSlice = rt.byteSliceRange(rt.byteSliceFrom(bytes2), 1);
const base2: rt.Place<rt.u8> = rt.byteSliceAsPtr(s);
const first2: rt.Place<rt.u8> = rt.optionUnwrap(rt.iterToOption(rt.iterSliceMut(rt.byteSliceView(s)).next()));
const last: rt.Place<rt.u8> = rt.optionUnwrap(rt.iterLast(rt.iterSliceMut(rt.byteSliceView(s))));
const part2: rt.Place<rt.u8> = rt.byteSliceAsPtr(rt.byteSliceSplitAt(s, 2)[1]);
rt.byteVecPush(out, rt.ptrOffsetFrom(first2, base2) & 0xff);
rt.byteVecPush(out, rt.ptrOffsetFrom(last, base2) & 0xff);
rt.byteVecPush(out, rt.ptrOffsetFrom(base2, last) & 0xff);
rt.byteVecPush(out, rt.ptrOffsetFrom(part2, first2) & 0xff);
const _433: rt.Place<rt.u8> = rt.ptrAdd(last, rt.ptrOffsetFrom(part2, last));
_433.v = _433.v ^ 255;
rt.iterExtendBytes(out, rt.iterSlice(bytes2), undefined, true);
}

/**
Expand Down
21 changes: 19 additions & 2 deletions ts/fixtures/lang/src/elements.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,8 @@ pub fn inline(data: &[u8], out: &mut Vec<u8>) {
/// the array of one Rust treats it as, and into a mutable part of an array, measured from
/// the array, the pointer an empty slice keeps, within a shared part, which JS copies,
/// a `&mut` into that part, memory nothing wrote copied, null and dangling pointers moved by
/// address, kept by empty raw slices, and cast from pointers to arrays, and the crate's
/// functions named as std's.
/// address, kept by empty raw slices, and cast from pointers to arrays, the crate's
/// functions named as std's, and byte pointers into one buffer through its views.
pub fn edges(data: &[u8], out: &mut Vec<u8>) {
for &n in data {
let bytes = [n, 1, 2, 3];
Expand Down Expand Up @@ -400,6 +400,23 @@ pub fn edges(data: &[u8], out: &mut Vec<u8>) {
.is_null() as u8,
);
}
// Byte pointers into one buffer through different views of it: a subslice's own, its
// iterator's elements', and its parts'.
let mut bytes = [data.first().copied().unwrap_or(0), 1, 2, 3, 4, 5];
let s = &mut bytes[1..];
let base = s.as_mut_ptr();
let first: *mut u8 = s.iter_mut().next().unwrap();
let last: *mut u8 = s.iter_mut().last().unwrap();
let (_, tail) = s.split_at_mut(2);
let part = tail.as_mut_ptr();
unsafe {
out.push(first.offset_from(base) as u8);
out.push(last.offset_from(base) as u8);
out.push(base.offset_from(last) as u8);
out.push(part.offset_from(first) as u8);
*last.offset(part.offset_from(last)) ^= 0xff;
}
out.extend(bytes);
}

/// Raw pointers to slices, each where it starts and how long it is: read and written
Expand Down
10 changes: 7 additions & 3 deletions ts/runtime/rt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -293,13 +293,17 @@ export function ptrWrappingAdd<T>(p: Place<T>, n: number, size: number, align: n
return new AtIndex(e.array, wrapIndex(e.index, n | 0, size));
}

/** `p.offset_from(origin)`: how many elements `p` is past `origin`, in the same array. */
/** `p.offset_from(origin)`: how many elements `p` is past `origin`, in the same array or byte buffer. */
export function ptrOffsetFrom<T>(p: Place<T>, origin: Place<T>): number {
// Equal addresses are none apart, in no allocation as in one.
if (p === origin || (p instanceof Address && origin instanceof Address && p.addr === origin.addr)) return 0;
const [a, b] = [elemOf(p), elemOf(origin)];
if (a.array !== b.array) throw new Error("rust2-ts: `offset_from` of pointers JS keeps in different arrays");
return a.index - b.index;
if (a.array === b.array) return a.index - b.index;
// Views of one buffer's bytes, such as a slice's and its iterator's, are one array.
if (a.array instanceof Uint8Array && b.array instanceof Uint8Array && a.array.buffer === b.array.buffer) {
return a.array.byteOffset + a.index - (b.array.byteOffset + b.index);
}
throw new Error("rust2-ts: `offset_from` of pointers JS keeps in different arrays");
}

/**
Expand Down