marshal.odin 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. package json
  2. import "core:mem"
  3. import "core:math/bits"
  4. import "core:runtime"
  5. import "core:strconv"
  6. import "core:strings"
  7. import "core:io"
  8. Marshal_Data_Error :: enum {
  9. None,
  10. Unsupported_Type,
  11. }
  12. Marshal_Error :: union #shared_nil {
  13. Marshal_Data_Error,
  14. io.Error,
  15. }
  16. marshal :: proc(v: any, allocator := context.allocator) -> (data: []byte, err: Marshal_Error) {
  17. b := strings.builder_make(allocator)
  18. defer if err != nil {
  19. strings.builder_destroy(&b)
  20. }
  21. marshal_to_builder(&b, v) or_return
  22. if len(b.buf) != 0 {
  23. data = b.buf[:]
  24. }
  25. return data, nil
  26. }
  27. marshal_to_builder :: proc(b: ^strings.Builder, v: any) -> Marshal_Error {
  28. return marshal_to_writer(strings.to_writer(b), v)
  29. }
  30. marshal_to_writer :: proc(w: io.Writer, v: any) -> (err: Marshal_Error) {
  31. if v == nil {
  32. io.write_string(w, "null") or_return
  33. return
  34. }
  35. ti := runtime.type_info_base(type_info_of(v.id))
  36. a := any{v.data, ti.id}
  37. switch info in ti.variant {
  38. case runtime.Type_Info_Named:
  39. unreachable()
  40. case runtime.Type_Info_Integer:
  41. buf: [40]byte
  42. u: u128
  43. switch i in a {
  44. case i8: u = u128(i)
  45. case i16: u = u128(i)
  46. case i32: u = u128(i)
  47. case i64: u = u128(i)
  48. case int: u = u128(i)
  49. case u8: u = u128(i)
  50. case u16: u = u128(i)
  51. case u32: u = u128(i)
  52. case u64: u = u128(i)
  53. case u128: u = u128(i)
  54. case uint: u = u128(i)
  55. case uintptr: u = u128(i)
  56. case i16le: u = u128(i)
  57. case i32le: u = u128(i)
  58. case i64le: u = u128(i)
  59. case u16le: u = u128(i)
  60. case u32le: u = u128(i)
  61. case u64le: u = u128(i)
  62. case u128le: u = u128(i)
  63. case i16be: u = u128(i)
  64. case i32be: u = u128(i)
  65. case i64be: u = u128(i)
  66. case u16be: u = u128(i)
  67. case u32be: u = u128(i)
  68. case u64be: u = u128(i)
  69. case u128be: u = u128(i)
  70. }
  71. s := strconv.append_bits_128(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil)
  72. io.write_string(w, s) or_return
  73. case runtime.Type_Info_Rune:
  74. r := a.(rune)
  75. io.write_byte(w, '"') or_return
  76. io.write_escaped_rune(w, r, '"', true) or_return
  77. io.write_byte(w, '"') or_return
  78. case runtime.Type_Info_Float:
  79. switch f in a {
  80. case f16: io.write_f16(w, f) or_return
  81. case f32: io.write_f32(w, f) or_return
  82. case f64: io.write_f64(w, f) or_return
  83. case: return .Unsupported_Type
  84. }
  85. case runtime.Type_Info_Complex:
  86. r, i: f64
  87. switch z in a {
  88. case complex32: r, i = f64(real(z)), f64(imag(z))
  89. case complex64: r, i = f64(real(z)), f64(imag(z))
  90. case complex128: r, i = f64(real(z)), f64(imag(z))
  91. case: return .Unsupported_Type
  92. }
  93. io.write_byte(w, '[') or_return
  94. io.write_f64(w, r) or_return
  95. io.write_string(w, ", ") or_return
  96. io.write_f64(w, i) or_return
  97. io.write_byte(w, ']') or_return
  98. case runtime.Type_Info_Quaternion:
  99. return .Unsupported_Type
  100. case runtime.Type_Info_String:
  101. switch s in a {
  102. case string: io.write_quoted_string(w, s) or_return
  103. case cstring: io.write_quoted_string(w, string(s)) or_return
  104. }
  105. case runtime.Type_Info_Boolean:
  106. val: bool
  107. switch b in a {
  108. case bool: val = bool(b)
  109. case b8: val = bool(b)
  110. case b16: val = bool(b)
  111. case b32: val = bool(b)
  112. case b64: val = bool(b)
  113. }
  114. io.write_string(w, val ? "true" : "false") or_return
  115. case runtime.Type_Info_Any:
  116. return .Unsupported_Type
  117. case runtime.Type_Info_Type_Id:
  118. return .Unsupported_Type
  119. case runtime.Type_Info_Pointer:
  120. return .Unsupported_Type
  121. case runtime.Type_Info_Multi_Pointer:
  122. return .Unsupported_Type
  123. case runtime.Type_Info_Procedure:
  124. return .Unsupported_Type
  125. case runtime.Type_Info_Tuple:
  126. return .Unsupported_Type
  127. case runtime.Type_Info_Simd_Vector:
  128. return .Unsupported_Type
  129. case runtime.Type_Info_Relative_Pointer:
  130. return .Unsupported_Type
  131. case runtime.Type_Info_Relative_Slice:
  132. return .Unsupported_Type
  133. case runtime.Type_Info_Matrix:
  134. return .Unsupported_Type
  135. case runtime.Type_Info_Array:
  136. io.write_byte(w, '[') or_return
  137. for i in 0..<info.count {
  138. if i > 0 { io.write_string(w, ", ") or_return }
  139. data := uintptr(v.data) + uintptr(i*info.elem_size)
  140. marshal_to_writer(w, any{rawptr(data), info.elem.id}) or_return
  141. }
  142. io.write_byte(w, ']') or_return
  143. case runtime.Type_Info_Enumerated_Array:
  144. index := runtime.type_info_base(info.index).variant.(runtime.Type_Info_Enum)
  145. io.write_byte(w, '[') or_return
  146. for i in 0..<info.count {
  147. if i > 0 { io.write_string(w, ", ") or_return }
  148. data := uintptr(v.data) + uintptr(i*info.elem_size)
  149. marshal_to_writer(w, any{rawptr(data), info.elem.id}) or_return
  150. }
  151. io.write_byte(w, ']') or_return
  152. case runtime.Type_Info_Dynamic_Array:
  153. io.write_byte(w, '[') or_return
  154. array := cast(^mem.Raw_Dynamic_Array)v.data
  155. for i in 0..<array.len {
  156. if i > 0 { io.write_string(w, ", ") or_return }
  157. data := uintptr(array.data) + uintptr(i*info.elem_size)
  158. marshal_to_writer(w, any{rawptr(data), info.elem.id}) or_return
  159. }
  160. io.write_byte(w, ']') or_return
  161. case runtime.Type_Info_Slice:
  162. io.write_byte(w, '[') or_return
  163. slice := cast(^mem.Raw_Slice)v.data
  164. for i in 0..<slice.len {
  165. if i > 0 { io.write_string(w, ", ") or_return }
  166. data := uintptr(slice.data) + uintptr(i*info.elem_size)
  167. marshal_to_writer(w, any{rawptr(data), info.elem.id}) or_return
  168. }
  169. io.write_byte(w, ']') or_return
  170. case runtime.Type_Info_Map:
  171. m := (^mem.Raw_Map)(v.data)
  172. io.write_byte(w, '{') or_return
  173. if m != nil {
  174. if info.generated_struct == nil {
  175. return .Unsupported_Type
  176. }
  177. entries := &m.entries
  178. gs := runtime.type_info_base(info.generated_struct).variant.(runtime.Type_Info_Struct)
  179. ed := runtime.type_info_base(gs.types[1]).variant.(runtime.Type_Info_Dynamic_Array)
  180. entry_type := ed.elem.variant.(runtime.Type_Info_Struct)
  181. entry_size := ed.elem_size
  182. for i in 0..<entries.len {
  183. if i > 0 { io.write_string(w, ", ") or_return }
  184. data := uintptr(entries.data) + uintptr(i*entry_size)
  185. key := rawptr(data + entry_type.offsets[2])
  186. value := rawptr(data + entry_type.offsets[3])
  187. marshal_to_writer(w, any{key, info.key.id}) or_return
  188. io.write_string(w, ": ") or_return
  189. marshal_to_writer(w, any{value, info.value.id}) or_return
  190. }
  191. }
  192. io.write_byte(w, '}') or_return
  193. case runtime.Type_Info_Struct:
  194. io.write_byte(w, '{') or_return
  195. for name, i in info.names {
  196. if i > 0 { io.write_string(w, ", ") or_return }
  197. io.write_quoted_string(w, name) or_return
  198. io.write_string(w, ": ") or_return
  199. id := info.types[i].id
  200. data := rawptr(uintptr(v.data) + info.offsets[i])
  201. marshal_to_writer(w, any{data, id}) or_return
  202. }
  203. io.write_byte(w, '}') or_return
  204. case runtime.Type_Info_Union:
  205. tag_ptr := uintptr(v.data) + info.tag_offset
  206. tag_any := any{rawptr(tag_ptr), info.tag_type.id}
  207. tag: i64 = -1
  208. switch i in tag_any {
  209. case u8: tag = i64(i)
  210. case i8: tag = i64(i)
  211. case u16: tag = i64(i)
  212. case i16: tag = i64(i)
  213. case u32: tag = i64(i)
  214. case i32: tag = i64(i)
  215. case u64: tag = i64(i)
  216. case i64: tag = i64(i)
  217. case: panic("Invalid union tag type")
  218. }
  219. if v.data == nil || tag == 0 {
  220. io.write_string(w, "null") or_return
  221. } else {
  222. id := info.variants[tag-1].id
  223. return marshal_to_writer(w, any{v.data, id})
  224. }
  225. case runtime.Type_Info_Enum:
  226. return marshal_to_writer(w, any{v.data, info.base.id})
  227. case runtime.Type_Info_Bit_Set:
  228. is_bit_set_different_endian_to_platform :: proc(ti: ^runtime.Type_Info) -> bool {
  229. if ti == nil {
  230. return false
  231. }
  232. t := runtime.type_info_base(ti)
  233. #partial switch info in t.variant {
  234. case runtime.Type_Info_Integer:
  235. switch info.endianness {
  236. case .Platform: return false
  237. case .Little: return ODIN_ENDIAN != .Little
  238. case .Big: return ODIN_ENDIAN != .Big
  239. }
  240. }
  241. return false
  242. }
  243. bit_data: u64
  244. bit_size := u64(8*ti.size)
  245. do_byte_swap := is_bit_set_different_endian_to_platform(info.underlying)
  246. switch bit_size {
  247. case 0: bit_data = 0
  248. case 8:
  249. x := (^u8)(v.data)^
  250. bit_data = u64(x)
  251. case 16:
  252. x := (^u16)(v.data)^
  253. if do_byte_swap {
  254. x = bits.byte_swap(x)
  255. }
  256. bit_data = u64(x)
  257. case 32:
  258. x := (^u32)(v.data)^
  259. if do_byte_swap {
  260. x = bits.byte_swap(x)
  261. }
  262. bit_data = u64(x)
  263. case 64:
  264. x := (^u64)(v.data)^
  265. if do_byte_swap {
  266. x = bits.byte_swap(x)
  267. }
  268. bit_data = u64(x)
  269. case: panic("unknown bit_size size")
  270. }
  271. io.write_u64(w, bit_data) or_return
  272. return .Unsupported_Type
  273. }
  274. return
  275. }