Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to read the real byteOffset? #928

Closed
zie1ony opened this issue Oct 25, 2019 · 7 comments
Closed

How to read the real byteOffset? #928

zie1ony opened this issue Oct 25, 2019 · 7 comments
Labels

Comments

@zie1ony
Copy link

zie1ony commented Oct 25, 2019

I try to read an array of bytes on my host:

@external("env", "read_bytes")
declare function read_bytes(
  ptr: i32,
  size: i32,
): void;

export function call(): void {
    var value = new Uint8Array(3);
    value[0] = 1;
    value[1] = 2;
    value[2] = 3;
    read_bytes(
        value.byteOffset, // returns 0
        value.byteLength
    );

    var value2 = new Uint8Array(3);
    value2[0] = 4;
    value2[1] = 5;
    value2[2] = 6;
    read_bytes(
        value2.byteOffset,  // returns 0
        value2.byteLength
    );
}

I expected byteOffset to return a point in WASM memory where structure starts, but it doesn't work like that.

I have the solution, that works fine in Rust:

let bytes: [u8; 32] = [255u8; 32];
let ptr = bytes.as_ptr();
let size = bytes.len();

unsafe {
    read_bytes(ptr, size);
}

Is it possible to have something similar in AssemblyScript?

@MaxGraey
Copy link
Member

MaxGraey commented Oct 25, 2019

byteOffset is not pointer to backing storage of TypedArrays. You should use value.dataStart or changetype<usize>(value.buffer) + value.byteOffset instead.

@zie1ony
Copy link
Author

zie1ony commented Oct 25, 2019

Great, value.dataStart works as expected.

I see in docs https://docs.assemblyscript.org/details/memory#arraybufferview-layout there should be also dataLength method, but it doesn't compile.

ERROR TS2339: Property 'dataLength' does not exist on type '~lib/arraybuffer/ArrayBufferView'.

I ended up with:

read_bytes(
    value.dataStart,
    value.byteLength
);

@zie1ony zie1ony closed this as completed Oct 25, 2019
@MaxGraey
Copy link
Member

Yes. That chapter required updates.

@zie1ony
Copy link
Author

zie1ony commented Oct 27, 2019

I have follow up question here. How to reproduce Uint8Array given a pointer and a size? I think of something like load<Uint8Array>(value.dataStart, value.byteLength), but value.byteLength needs to be know at compile size. And I got lost :(

@zie1ony zie1ony reopened this Oct 27, 2019
@MaxGraey
Copy link
Member

MaxGraey commented Oct 27, 2019

// for Uint8Array

const arr = Uint8Array.wrap(
  changetype<ArrayBuffer>(value.dataStart),
  value.byteOffset, // or `0`
  value.byteLength // same value.byteLength >> alignof<u8>() or value.length
)

// for Uint32Array

const arr = Uint32Array.wrap(
  changetype<ArrayBuffer>(value.dataStart),
  value.byteOffset, // or `0`
  value.byteLength >> alignof<u32>()  // or value.length
)

// and etc

<TypedArray>.wrap in docs

@zie1ony
Copy link
Author

zie1ony commented Oct 27, 2019

Thank you one more time.
I managed to write smart contract for CasperLabs platform using AssemblyScript and your help.
https://github.com/zie1ony/casperlabs-assemblyscript-transfer-to-account

@zie1ony zie1ony closed this as completed Oct 27, 2019
@MaxGraey
Copy link
Member

Nice!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants