marshal.odin 8.3 KB

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