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

[core:encoding/json] Incorrect bit_set Value When Unmarshalling #4761

Open
dozn opened this issue Jan 26, 2025 · 1 comment
Open

[core:encoding/json] Incorrect bit_set Value When Unmarshalling #4761

dozn opened this issue Jan 26, 2025 · 1 comment

Comments

@dozn
Copy link
Contributor

dozn commented Jan 26, 2025

Context

package main
import "core:encoding/json"
import "core:fmt"
main :: proc() {
  Entity :: bit_set[EntityFlag; u64]
  EntityFlag :: enum { Player }
  save_data := Entity{.Player}
  fmt.println("original: ", save_data)

  bytes, err_marshal := json.marshal(save_data)
  if err_marshal != nil { fmt.panicf("%s", err_marshal) }
  fmt.println("marshal:  ", string(bytes))

  save_data = {}
  if err_unmarshal := json.unmarshal(bytes, &save_data); err_unmarshal != nil {
    fmt.panicf("%s", err_unmarshal)
  }
  fmt.println("unmarshal:", save_data)
}

Expected Behavior

original:  bit_set[EntityFlag; u64]{Player}
marshal:   1
unmarshal: bit_set[EntityFlag; u64]{Player}

Current Behavior

original:  bit_set[EntityFlag; u64]{Player}
marshal:   1
unmarshal: bit_set[EntityFlag; u64]{56}

Notes

  • cbor works
  • works when i/u8, broken with 16/32/64
  • it's hitting the byte_swaps at
    x^ = do_byte_swap ? intrinsics.byte_swap(u16(i)) : u16(i)
    case 32:
    x := (^u32)(v.data)
    x^ = do_byte_swap ? intrinsics.byte_swap(u32(i)) : u32(i)
    case 64:
    x := (^u64)(v.data)
    x^ = do_byte_swap ? intrinsics.byte_swap(u64(i)) : u64(i)
    which messes up the values (see comment by Barinzaya), because it's hitting
    case .Platform: return ODIN_ENDIAN == .Big
    and thinks it's big endian

Odin: dev-2025-01:bca016ae9
OS: Windows 11 Professional (version: 23H2), build 22631.4751
CPU: AMD Ryzen 7 3700X 8-Core Processor
RAM: 65457 MiB
Backend: LLVM 18.1.8

@Barinzaya
Copy link
Contributor

Barinzaya commented Jan 26, 2025

It doesn't look like the problem is that it thinks the bit_set is big endian, it looks like the logic for when to swap bytes is wrong.

do_byte_swap := !reflect.bit_set_is_big_endian(v)

This swaps the bytes whenever the bit_set isn't big endian--meaning it always makes the bit_set big endian swaps the bytes when the bit set is little endian, regardless of the platform. Seems like it should be:

do_byte_swap := reflect.bit_set_is_big_endian(v) != (ODIN_ENDIAN == .Big)

or equivalent. Basically, swap the bytes when the bit_set's endianness is different from the platform's.

@dozn dozn changed the title Incorrect bit_set Value When Unmarshalling [core:encoding/json] Incorrect bit_set Value When Unmarshalling Jan 26, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants