write.odin 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. package encoding_hxa
  2. import "core:os"
  3. import "core:mem"
  4. Write_Error :: enum {
  5. None,
  6. Buffer_Too_Small,
  7. Failed_File_Write,
  8. }
  9. write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) {
  10. required := required_write_size(file);
  11. buf, alloc_err := make([]byte, required);
  12. if alloc_err == .Out_Of_Memory {
  13. return .Failed_File_Write;
  14. }
  15. defer delete(buf);
  16. write_internal(&Writer{data = buf}, file);
  17. if !os.write_entire_file(filepath, buf) {
  18. err =.Failed_File_Write;
  19. }
  20. return;
  21. }
  22. write :: proc(buf: []byte, file: File) -> (n: int, err: Write_Error) {
  23. required := required_write_size(file);
  24. if len(buf) < required {
  25. err = .Buffer_Too_Small;
  26. return;
  27. }
  28. n = required;
  29. write_internal(&Writer{data = buf}, file);
  30. return;
  31. }
  32. required_write_size :: proc(file: File) -> (n: int) {
  33. writer := &Writer{dummy_pass = true};
  34. write_internal(writer, file);
  35. n = writer.offset;
  36. return;
  37. }
  38. @(private)
  39. Writer :: struct {
  40. data: []byte,
  41. offset: int,
  42. dummy_pass: bool,
  43. };
  44. @(private)
  45. write_internal :: proc(w: ^Writer, file: File) {
  46. write_value :: proc(w: ^Writer, value: $T) {
  47. if !w.dummy_pass {
  48. remaining := len(w.data) - w.offset;
  49. assert(size_of(T) <= remaining);
  50. ptr := raw_data(w.data[w.offset:]);
  51. (^T)(ptr)^ = value;
  52. }
  53. w.offset += size_of(T);
  54. }
  55. write_array :: proc(w: ^Writer, array: []$T) {
  56. if !w.dummy_pass {
  57. remaining := len(w.data) - w.offset;
  58. assert(size_of(T)*len(array) <= remaining);
  59. ptr := raw_data(w.data[w.offset:]);
  60. dst := mem.slice_ptr((^T)(ptr), len(array));
  61. copy(dst, array);
  62. }
  63. w.offset += size_of(T)*len(array);
  64. }
  65. write_string :: proc(w: ^Writer, str: string) {
  66. if !w.dummy_pass {
  67. remaining := len(w.data) - w.offset;
  68. assert(size_of(byte)*len(str) <= remaining);
  69. ptr := raw_data(w.data[w.offset:]);
  70. dst := mem.slice_ptr((^byte)(ptr), len(str));
  71. copy(dst, str);
  72. }
  73. w.offset += size_of(byte)*len(str);
  74. }
  75. write_metadata :: proc(w: ^Writer, meta_data: []Meta) {
  76. for m in meta_data {
  77. name_len := max(len(m.name), 255);
  78. write_value(w, u8(name_len));
  79. write_string(w, m.name[:name_len]);
  80. meta_data_type: Meta_Value_Type;
  81. length: u32le = 0;
  82. switch v in m.value {
  83. case []i64le:
  84. meta_data_type = .Int64;
  85. length = u32le(len(v));
  86. case []f64le:
  87. meta_data_type = .Double;
  88. length = u32le(len(v));
  89. case []Node_Index:
  90. meta_data_type = .Node;
  91. length = u32le(len(v));
  92. case string:
  93. meta_data_type = .Text;
  94. length = u32le(len(v));
  95. case []byte:
  96. meta_data_type = .Binary;
  97. length = u32le(len(v));
  98. case []Meta:
  99. meta_data_type = .Meta;
  100. length = u32le(len(v));
  101. }
  102. write_value(w, meta_data_type);
  103. write_value(w, length);
  104. switch v in m.value {
  105. case []i64le: write_array(w, v);
  106. case []f64le: write_array(w, v);
  107. case []Node_Index: write_array(w, v);
  108. case string: write_string(w, v);
  109. case []byte: write_array(w, v);
  110. case []Meta: write_metadata(w, v);
  111. }
  112. }
  113. return;
  114. }
  115. write_layer_stack :: proc(w: ^Writer, layers: Layer_Stack) {
  116. write_value(w, u32(len(layers)));
  117. for layer in layers {
  118. name_len := max(len(layer.name), 255);
  119. write_value(w, u8(name_len));
  120. write_string(w, layer .name[:name_len]);
  121. write_value(w, layer.components);
  122. layer_data_type: Layer_Data_Type;
  123. switch v in layer.data {
  124. case []u8: layer_data_type = .Uint8;
  125. case []i32le: layer_data_type = .Int32;
  126. case []f32le: layer_data_type = .Float;
  127. case []f64le: layer_data_type = .Double;
  128. }
  129. write_value(w, layer_data_type);
  130. switch v in layer.data {
  131. case []u8: write_array(w, v);
  132. case []i32le: write_array(w, v);
  133. case []f32le: write_array(w, v);
  134. case []f64le: write_array(w, v);
  135. }
  136. }
  137. return;
  138. }
  139. write_value(w, &Header{
  140. magic_number = MAGIC_NUMBER,
  141. version = LATEST_VERSION,
  142. internal_node_count = u32le(len(file.nodes)),
  143. });
  144. for node in file.nodes {
  145. node_type: Node_Type;
  146. switch content in node.content {
  147. case Node_Geometry: node_type = .Geometry;
  148. case Node_Image: node_type = .Image;
  149. }
  150. write_value(w, node_type);
  151. write_value(w, u32(len(node.meta_data)));
  152. write_metadata(w, node.meta_data);
  153. switch content in node.content {
  154. case Node_Geometry:
  155. write_value(w, content.vertex_count);
  156. write_layer_stack(w, content.vertex_stack);
  157. write_value(w, content.edge_corner_count);
  158. write_layer_stack(w, content.corner_stack);
  159. write_layer_stack(w, content.edge_stack);
  160. write_value(w, content.face_count);
  161. write_layer_stack(w, content.face_stack);
  162. case Node_Image:
  163. write_value(w, content.type);
  164. dimensions := int(content.type);
  165. if content.type == .Image_Cube {
  166. dimensions = 2;
  167. }
  168. for d in 0..<dimensions {
  169. write_value(w, content.resolution[d]);
  170. }
  171. write_layer_stack(w, content.image_stack);
  172. }
  173. }
  174. }