-
Notifications
You must be signed in to change notification settings - Fork 0
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
make js code correct on little + big endian #515
Comments
swap endian-ness (to add support for std/endian in js): https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView/getInt32
eg how to use it: https://www.i-programmer.info/programming/javascript/6151-javascript-data-structures-typed-arrays-ii.html?start=1
other linkshttps://exploringjs.com/impatient-js/ch_typed-arrays.html nodejs |
The full codebase when defined(js):
import std/jsbigints
type
ArrayBuffer* = ref object of JsRoot
Float64Array* = ref object of JsRoot
Uint32Array* = ref object of JsRoot
BigUint64Array* = ref object of JsRoot
func newArrayBuffer*(n: int): ArrayBuffer {.importjs: "new ArrayBuffer(#)".}
func newFloat64Array*(buffer: ArrayBuffer): Float64Array {.importjs: "new Float64Array(#)".}
func newUint32Array*(buffer: ArrayBuffer): Uint32Array {.importjs: "new Uint32Array(#)".}
func newBigUint64Array*(buffer: ArrayBuffer): BigUint64Array {.importjs: "new BigUint64Array(#)".}
func `[]`*(arr: Uint32Array, i: int): uint32 {.importjs: "#[#]".}
func `[]`*(arr: BigUint64Array, i: int): JsBigInt {.importjs: "#[#]".}
func `[]=`*(arr: Float64Array, i: int, v: float) {.importjs: "#[#] = #".}
proc hasJsBigInt*(): bool =
asm """`result` = typeof BigInt != 'undefined'"""
when defined(js):
type
Uint16Array* = ref object of JsRoot
Uint8Array* = ref object of JsRoot
func buffer(p: Uint32Array): ArrayBuffer {.importjs: "#.buffer".}
func newUint32Array*(arr: openArray[uint32]): Uint32Array {.importjs: "new Uint32Array(#)".}
func newUint8Array(p: ArrayBuffer): Uint8Array {.importjs: "new Uint8Array(#)".}
func `[]`*(arr: Uint8Array, i: int): uint8 {.importjs: "#[#]".}
when defined(js):
when defined(nodejs):
{.emit: "const _nim_nodejs_os = require('os');".}
proc endianness(): cstring {.importjs: "_nim_nodejs_os.endianness()".}
template getEndiansJS(): Endianness =
if endianness() == "LE":
littleEndian
else:
bigEndian
else:
template getEndiansJS(): Endianness =
let a = newUint32Array([0x12345678'u32])
let b = newUint8Array(a.buffer)
if b[0] == 0x78:
littleEndian
else:
bigEndian
template getEndiansVM(): Endianness =
when defined(i386) or defined(alpha) or defined(powerpc64el) or
defined(ia64) or defined(amd64) or defined(mipsel) or defined(arm) or
defined(arm64) or defined(avr) or defined(msp430) or defined(riscv32) or
defined(riscv64) or defined(esp) or defined(wasm32) or defined(mips64el):
littleEndian
elif defined(m68k) or defined(powerpc) or defined(powerpc64) or defined(sparc) or
defined(hppa) or defined(mips) or defined(sparc64) or defined(mips64):
bigEndian
else:
littleEndian
proc getEndians(): Endianness {.inline.} =
when nimvm:
getEndiansVM()
else:
when defined(js):
result = getEndiansJS()
else:
result = cpuEndian
const cpuEndiansVM* = getEndians()
let cpuEndiansRT* = getEndians()
#
#
# Nim's Runtime Library
# (c) Copyright 2012 Andreas Rumpf
#
# See the file "copying.txt", included in this
# distribution, for details about the copyright.
#
## This module contains helpers that deal with different byte orders
## (`endian`:idx:).
##
## Unstable API.
when not defined(js):
template builtin_bswap(a: uint8): uint8 =
a
when defined(gcc) or defined(llvm_gcc) or defined(clang):
func builtin_bswap(a: uint16): uint16 {.
importc: "__builtin_bswap16", nodecl.}
func builtin_bswap(a: uint32): uint32 {.
importc: "__builtin_bswap32", nodecl.}
func builtin_bswap(a: uint64): uint64 {.
importc: "__builtin_bswap64", nodecl.}
elif defined(icc):
func builtin_bswap(a: uint16): uint16 {.
importc: "_bswap16", nodecl.}
func builtin_bswap(a: uint32): uint32 {.
importc: "_bswap", nodecl.}
func builtin_bswap(a: uint64): uint64 {.
importc: "_bswap64", nodecl.}
elif defined(vcc):
func builtin_bswap(a: uint16): uint16 {.
importc: "_byteswap_ushort", nodecl, header: "<intrin.h>".}
func builtin_bswap(a: uint32): uint32 {.
importc: "_byteswap_ulong", nodecl, header: "<intrin.h>".}
func builtin_bswap(a: uint64): uint64 {.
importc: "_byteswap_uint64", nodecl, header: "<intrin.h>".}
template builtin_bswapImpl(a: uint8): uint8 =
a
template builtin_bswapImpl(a: uint16): uint16 =
(a shl 8'u16) or (a shr 8'u16)
template builtin_bswapImpl(a: uint32): uint32 =
((a shl 24) and 0xff000000'u32) or
((a shl 8) and 0x00ff0000'u32) or
((a shr 8) and 0x0000ff00'u32) or
((a shr 24) and 0x000000ff'u32)
template builtin_bswapImpl(a: uint64): uint64 =
var num = (a shl 32'u64) or (a shr 32'u64)
num = ((num and 0x0000ffff0000ffff'u64) shl 16'u64) or
((num and 0xffff0000ffff0000'u64) shr 16'u64)
((num and 0x00ff00ff00ff00ff'u64) shl 8'u64) or
((num and 0xff00ff00ff00ff00'u64) shr 8'u64)
func swapEndian*[T: SomeUnsignedInt](a: T): T {.inline.} =
when nimvm:
result = builtin_bswapImpl(a)
else:
when defined(js):
result = builtin_bswapImpl(a)
else:
result = builtin_bswap(a)
proc toEndian[T: SomeUnsignedInt](a: T, endianess: static Endianness): T {.inline.} =
when nimvm:
when cpuEndiansVM == endianess:
result = swapEndian(a)
else:
result = a
else:
when defined(js):
if cpuEndiansRT == endianess:
result = swapEndian(a)
else:
result = a
else:
when cpuEndiansVM == endianess:
result = swapEndian(a)
else:
result = a
proc toBigEndian*[T: SomeUnsignedInt](a: T): T {.inline.} =
result = toEndian(a, littleEndian)
proc toLittleEndian*[T: SomeUnsignedInt](a: T): T {.inline.} =
result = toEndian(a, bigEndian)
proc main() =
doAssert toLittleEndian(12'u32) == 12
doAssert toLittleEndian(12'u64) == 12
doAssert toLittleEndian(12'u16) == 12
doAssert toLittleEndian(12'u8) == 12
echo toBigEndian(12'u64)
doAssert toBigEndian(12'u32) == 201326592
doAssert toBigEndian(12'u16) == 3072
doAssert toBigEndian(12'u8) == 12
static: main()
main() |
seems like a good start! is |
some js code in nim (eg nim-lang#16592) uses implicit assumption of little endian; this is likely true for most platforms (even more so for js code) but still, it's not always correct.
example
proposal
use this (or better) from https://stackoverflow.com/questions/7869752/javascript-typed-arrays-and-endianness
then adapt code depending on
isBigEndian
Additional Information
1.5.1 d34d023
low priority because big endian is not a common thing in js
/cc @xflywind @juancarlospaco
links
https://riptutorial.com/javascript/example/13317/little---big-endian-for-typed-arrays-when-using-bitwise-operators see
Example where Edian type is important
let's assume littleEndian in JS backend by xflywind · Pull Request #16886 · nim-lang/Nim
make endians support JS backend by xflywind · Pull Request #16127 · nim-lang/Nim
endian independent views
https://stackoverflow.com/questions/63179879/should-i-care-about-big-endian-machines-while-using-uint32array
big endian machines
https://stackoverflow.com/questions/63179879/should-i-care-about-big-endian-machines-while-using-uint32array
The text was updated successfully, but these errors were encountered: