marshal.odin 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  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:reflect"
  8. Marshal_Error :: enum {
  9. None,
  10. Unsupported_Type,
  11. }
  12. marshal :: proc(v: any, allocator := context.allocator) -> ([]byte, Marshal_Error) {
  13. b := strings.make_builder(allocator);
  14. err := marshal_arg(&b, v);
  15. if err != Marshal_Error.None {
  16. strings.destroy_builder(&b);
  17. return nil, err;
  18. }
  19. if len(b.buf) == 0 {
  20. strings.destroy_builder(&b);
  21. return nil, err;
  22. }
  23. return b.buf[:], err;
  24. }
  25. marshal_arg :: proc(b: ^strings.Builder, v: any) -> Marshal_Error {
  26. using strings;
  27. using runtime;
  28. if v == nil {
  29. write_string(b, "null");
  30. return Marshal_Error.None;
  31. }
  32. ti := type_info_base(type_info_of(v.id));
  33. a := any{v.data, ti.id};
  34. switch info in ti.variant {
  35. case Type_Info_Named:
  36. panic("Unreachable");
  37. case Type_Info_Integer:
  38. buf: [21]byte;
  39. u: u64;
  40. switch i in a {
  41. case i8: u = u64(i);
  42. case i16: u = u64(i);
  43. case i32: u = u64(i);
  44. case i64: u = u64(i);
  45. case int: u = u64(i);
  46. case u8: u = u64(i);
  47. case u16: u = u64(i);
  48. case u32: u = u64(i);
  49. case u64: u = u64(i);
  50. case uint: u = u64(i);
  51. case uintptr: u = u64(i);
  52. case i16le: u = u64(i);
  53. case i32le: u = u64(i);
  54. case i64le: u = u64(i);
  55. case u16le: u = u64(i);
  56. case u32le: u = u64(i);
  57. case u64le: u = u64(i);
  58. case i16be: u = u64(i);
  59. case i32be: u = u64(i);
  60. case i64be: u = u64(i);
  61. case u16be: u = u64(i);
  62. case u32be: u = u64(i);
  63. case u64be: u = u64(i);
  64. }
  65. s := strconv.append_bits(buf[:], u, 10, info.signed, 8*ti.size, "0123456789", nil);
  66. write_string(b, s);
  67. case Type_Info_Rune:
  68. r := a.(rune);
  69. write_byte(b, '"');
  70. write_escaped_rune(b, r, '"', true);
  71. write_byte(b, '"');
  72. case Type_Info_Float:
  73. val: f64;
  74. switch f in a {
  75. case f32: val = f64(f);
  76. case f64: val = f64(f);
  77. }
  78. buf: [386]byte;
  79. str := strconv.append_float(buf[1:], val, 'f', 2*ti.size, 8*ti.size);
  80. str = string(buf[:len(str)+1]);
  81. if str[1] == '+' || str[1] == '-' {
  82. str = str[1:];
  83. } else {
  84. str[0] = '+';
  85. }
  86. if str[0] == '+' {
  87. str = str[1:];
  88. }
  89. write_string(b, str);
  90. case Type_Info_Complex:
  91. return Marshal_Error.Unsupported_Type;
  92. case Type_Info_String:
  93. switch s in a {
  94. case string: write_quoted_string(b, s);
  95. case cstring: write_quoted_string(b, string(s));
  96. }
  97. case Type_Info_Boolean:
  98. val: bool;
  99. switch b in a {
  100. case bool: val = bool(b);
  101. case b8: val = bool(b);
  102. case b16: val = bool(b);
  103. case b32: val = bool(b);
  104. case b64: val = bool(b);
  105. }
  106. write_string(b, val ? "true" : "false");
  107. case Type_Info_Any:
  108. return Marshal_Error.Unsupported_Type;
  109. case Type_Info_Type_Id:
  110. return Marshal_Error.Unsupported_Type;
  111. case Type_Info_Pointer:
  112. return Marshal_Error.Unsupported_Type;
  113. case Type_Info_Procedure:
  114. return Marshal_Error.Unsupported_Type;
  115. case Type_Info_Tuple:
  116. return Marshal_Error.Unsupported_Type;
  117. case Type_Info_Array:
  118. write_byte(b, '[');
  119. for i in 0..<info.count {
  120. if i > 0 do write_string(b, ", ");
  121. data := uintptr(v.data) + uintptr(i*info.elem_size);
  122. marshal_arg(b, any{rawptr(data), info.elem.id});
  123. }
  124. write_byte(b, ']');
  125. case Type_Info_Dynamic_Array:
  126. write_byte(b, '[');
  127. array := cast(^mem.Raw_Dynamic_Array)v.data;
  128. for i in 0..<array.len {
  129. if i > 0 do write_string(b, ", ");
  130. data := uintptr(array.data) + uintptr(i*info.elem_size);
  131. marshal_arg(b, any{rawptr(data), info.elem.id});
  132. }
  133. write_byte(b, ']');
  134. case Type_Info_Slice:
  135. write_byte(b, '[');
  136. slice := cast(^mem.Raw_Slice)v.data;
  137. for i in 0..<slice.len {
  138. if i > 0 do write_string(b, ", ");
  139. data := uintptr(slice.data) + uintptr(i*info.elem_size);
  140. marshal_arg(b, any{rawptr(data), info.elem.id});
  141. }
  142. write_byte(b, ']');
  143. case Type_Info_Map:
  144. m := (^mem.Raw_Map)(v.data);
  145. write_byte(b, '{');
  146. if m != nil {
  147. if info.generated_struct == nil {
  148. return Marshal_Error.Unsupported_Type;
  149. }
  150. entries := &m.entries;
  151. gs := type_info_base(info.generated_struct).variant.(Type_Info_Struct);
  152. ed := type_info_base(gs.types[1]).variant.(Type_Info_Dynamic_Array);
  153. entry_type := ed.elem.variant.(Type_Info_Struct);
  154. entry_size := ed.elem_size;
  155. for i in 0..<entries.len {
  156. if i > 0 do write_string(b, ", ");
  157. data := uintptr(entries.data) + uintptr(i*entry_size);
  158. header := cast(^Map_Entry_Header)data;
  159. if reflect.is_string(info.key) {
  160. marshal_arg(b, header.key.str);
  161. } else {
  162. marshal_arg(b, any{rawptr(&header.key.hash), info.key.id});
  163. }
  164. write_string(b, ": ");
  165. value := data + entry_type.offsets[2];
  166. marshal_arg(b, any{rawptr(value), info.value.id});
  167. }
  168. }
  169. write_byte(b, '}');
  170. case Type_Info_Struct:
  171. write_byte(b, '{');
  172. for name, i in info.names {
  173. if i > 0 do write_string(b, ", ");
  174. write_quoted_string(b, name);
  175. write_string(b, ": ");
  176. id := info.types[i].id;
  177. data := rawptr(uintptr(v.data) + info.offsets[i]);
  178. marshal_arg(b, any{data, id});
  179. }
  180. write_byte(b, '}');
  181. case Type_Info_Union:
  182. tag_ptr := uintptr(v.data) + info.tag_offset;
  183. tag_any := any{rawptr(tag_ptr), info.tag_type.id};
  184. tag: i64 = -1;
  185. switch i in tag_any {
  186. case u8: tag = i64(i);
  187. case i8: tag = i64(i);
  188. case u16: tag = i64(i);
  189. case i16: tag = i64(i);
  190. case u32: tag = i64(i);
  191. case i32: tag = i64(i);
  192. case u64: tag = i64(i);
  193. case i64: tag = i64(i);
  194. case: panic("Invalid union tag type");
  195. }
  196. if v.data == nil || tag == 0 {
  197. write_string(b, "null");
  198. } else {
  199. id := info.variants[tag-1].id;
  200. marshal_arg(b, any{v.data, id});
  201. }
  202. case Type_Info_Enum:
  203. return marshal_arg(b, any{v.data, info.base.id});
  204. case Type_Info_Bit_Field:
  205. data: u64 = 0;
  206. switch ti.size {
  207. case 1: data = cast(u64) (^u8)(v.data)^;
  208. case 2: data = cast(u64)(^u16)(v.data)^;
  209. case 4: data = cast(u64)(^u32)(v.data)^;
  210. case 8: data = cast(u64)(^u64)(v.data)^;
  211. }
  212. write_byte(b, '{');
  213. for name, i in info.names {
  214. if i > 0 do write_string(b, ", ");
  215. bits := u64(info.bits[i]);
  216. offset := u64(info.offsets[i]);
  217. marshal_arg(b, name);
  218. write_string(b, ": ");
  219. n := 8*u64(size_of(u64));
  220. sa := n - bits;
  221. u := data>>offset;
  222. u <<= sa;
  223. u >>= sa;
  224. write_u64(b, u, 10);
  225. }
  226. write_byte(b, '}');
  227. case 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. 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 do x = bits.byte_swap(x);
  254. bit_data = u64(x);
  255. case 32:
  256. x := (^u32)(v.data)^;
  257. if do_byte_swap do x = bits.byte_swap(x);
  258. bit_data = u64(x);
  259. case 64:
  260. x := (^u64)(v.data)^;
  261. if do_byte_swap do x = bits.byte_swap(x);
  262. bit_data = u64(x);
  263. case: panic("unknown bit_size size");
  264. }
  265. write_u64(b, bit_data);
  266. return Marshal_Error.Unsupported_Type;
  267. case Type_Info_Opaque:
  268. return Marshal_Error.Unsupported_Type;
  269. }
  270. return Marshal_Error.None;
  271. }