marshal.odin 8.6 KB

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