123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193 |
- package encoding_hxa
- import "core:os"
- import "core:mem"
- Write_Error :: enum {
- None,
- Buffer_Too_Small,
- Failed_File_Write,
- }
- write_to_file :: proc(filepath: string, file: File) -> (err: Write_Error) {
- required := required_write_size(file);
- buf, alloc_err := make([]byte, required);
- if alloc_err == .Out_Of_Memory {
- return .Failed_File_Write;
- }
- defer delete(buf);
- write_internal(&Writer{data = buf}, file);
- if !os.write_entire_file(filepath, buf) {
- err =.Failed_File_Write;
- }
- return;
- }
- write :: proc(buf: []byte, file: File) -> (n: int, err: Write_Error) {
- required := required_write_size(file);
- if len(buf) < required {
- err = .Buffer_Too_Small;
- return;
- }
- n = required;
- write_internal(&Writer{data = buf}, file);
- return;
- }
- required_write_size :: proc(file: File) -> (n: int) {
- writer := &Writer{dummy_pass = true};
- write_internal(writer, file);
- n = writer.offset;
- return;
- }
- @(private)
- Writer :: struct {
- data: []byte,
- offset: int,
- dummy_pass: bool,
- };
- @(private)
- write_internal :: proc(w: ^Writer, file: File) {
- write_value :: proc(w: ^Writer, value: $T) {
- if !w.dummy_pass {
- remaining := len(w.data) - w.offset;
- assert(size_of(T) <= remaining);
- ptr := raw_data(w.data[w.offset:]);
- (^T)(ptr)^ = value;
- }
- w.offset += size_of(T);
- }
- write_array :: proc(w: ^Writer, array: []$T) {
- if !w.dummy_pass {
- remaining := len(w.data) - w.offset;
- assert(size_of(T)*len(array) <= remaining);
- ptr := raw_data(w.data[w.offset:]);
- dst := mem.slice_ptr((^T)(ptr), len(array));
- copy(dst, array);
- }
- w.offset += size_of(T)*len(array);
- }
- write_string :: proc(w: ^Writer, str: string) {
- if !w.dummy_pass {
- remaining := len(w.data) - w.offset;
- assert(size_of(byte)*len(str) <= remaining);
- ptr := raw_data(w.data[w.offset:]);
- dst := mem.slice_ptr((^byte)(ptr), len(str));
- copy(dst, str);
- }
- w.offset += size_of(byte)*len(str);
- }
- write_metadata :: proc(w: ^Writer, meta_data: []Meta) {
- for m in meta_data {
- name_len := max(len(m.name), 255);
- write_value(w, u8(name_len));
- write_string(w, m.name[:name_len]);
- meta_data_type: Meta_Value_Type;
- length: u32le = 0;
- switch v in m.value {
- case []i64le:
- meta_data_type = .Int64;
- length = u32le(len(v));
- case []f64le:
- meta_data_type = .Double;
- length = u32le(len(v));
- case []Node_Index:
- meta_data_type = .Node;
- length = u32le(len(v));
- case string:
- meta_data_type = .Text;
- length = u32le(len(v));
- case []byte:
- meta_data_type = .Binary;
- length = u32le(len(v));
- case []Meta:
- meta_data_type = .Meta;
- length = u32le(len(v));
- }
- write_value(w, meta_data_type);
- write_value(w, length);
- switch v in m.value {
- case []i64le: write_array(w, v);
- case []f64le: write_array(w, v);
- case []Node_Index: write_array(w, v);
- case string: write_string(w, v);
- case []byte: write_array(w, v);
- case []Meta: write_metadata(w, v);
- }
- }
- return;
- }
- write_layer_stack :: proc(w: ^Writer, layers: Layer_Stack) {
- write_value(w, u32(len(layers)));
- for layer in layers {
- name_len := max(len(layer.name), 255);
- write_value(w, u8(name_len));
- write_string(w, layer .name[:name_len]);
- write_value(w, layer.components);
- layer_data_type: Layer_Data_Type;
- switch v in layer.data {
- case []u8: layer_data_type = .Uint8;
- case []i32le: layer_data_type = .Int32;
- case []f32le: layer_data_type = .Float;
- case []f64le: layer_data_type = .Double;
- }
- write_value(w, layer_data_type);
- switch v in layer.data {
- case []u8: write_array(w, v);
- case []i32le: write_array(w, v);
- case []f32le: write_array(w, v);
- case []f64le: write_array(w, v);
- }
- }
- return;
- }
- write_value(w, &Header{
- magic_number = MAGIC_NUMBER,
- version = LATEST_VERSION,
- internal_node_count = u32le(len(file.nodes)),
- });
- for node in file.nodes {
- node_type: Node_Type;
- switch content in node.content {
- case Node_Geometry: node_type = .Geometry;
- case Node_Image: node_type = .Image;
- }
- write_value(w, node_type);
- write_value(w, u32(len(node.meta_data)));
- write_metadata(w, node.meta_data);
- switch content in node.content {
- case Node_Geometry:
- write_value(w, content.vertex_count);
- write_layer_stack(w, content.vertex_stack);
- write_value(w, content.edge_corner_count);
- write_layer_stack(w, content.corner_stack);
- write_layer_stack(w, content.edge_stack);
- write_value(w, content.face_count);
- write_layer_stack(w, content.face_stack);
- case Node_Image:
- write_value(w, content.type);
- dimensions := int(content.type);
- if content.type == .Image_Cube {
- dimensions = 2;
- }
- for d in 0..<dimensions {
- write_value(w, content.resolution[d]);
- }
- write_layer_stack(w, content.image_stack);
- }
- }
- }
|