write.odin 4.6 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 := min(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 := min(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. }