this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 196 lines 4.2 kB view raw
1package addons 2 3import "core:fmt" 4import "core:reflect" 5import "core:strings" 6import "core:testing" 7 8Field_Error :: Maybe(string) 9 10@(private) 11Field_Type :: struct { 12 name: string, 13 type: ^reflect.Type_Info, 14 tag: string, 15 offset: int, 16} 17 18@(private) 19write_struct_field :: proc(obj: ^$T, field: Field_Type, value: $E) -> Field_Error { 20 if !(size_of(field.type.id) == size_of(E) || field.type.id == typeid_of(E)) { 21 return fmt.tprintf( 22 "given field {}.{} ({}) is not the same size as given value {}. {} != {}", 23 typeid_of(T), 24 field.name, 25 field.type.id, 26 typeid_of(E), 27 size_of(field.type.id), 28 size_of(E), 29 ) 30 } 31 32 obj_bytes := reflect.as_bytes(obj^) 33 value_bytes := reflect.as_bytes(value) 34 for i in 0 ..< len(value_bytes) { 35 obj_bytes[int(field.offset) + i] = value_bytes[i] 36 } 37 38 return nil 39} 40 41@(test) 42write_struct_field_test :: proc(t: ^testing.T) { 43 S :: struct($T: typeid) { 44 padding1: [13]u8 `sqlite:"Padding1"`, 45 value: T `sqlite:"Value"`, 46 padding2: [5]u8 `sqlite:"Padding2"`, 47 } 48 49 test_using_type :: proc(t: ^testing.T, value: $T) { 50 S1 :: S(T) 51 fields, err := get_type_fields(S1) 52 testing.expect(t, err == nil) 53 defer delete_field_types(fields) 54 55 value_field := fields[1] 56 obj: S1 57 58 err = write_struct_field(&obj, value_field, value) 59 testing.expect(t, err == nil) 60 testing.expect_value(t, obj.value, value) 61 62 // neighbours are unchanged 63 for b in obj.padding1 { 64 testing.expect(t, b == 0) 65 } 66 67 // neighbours are unchanged 68 for b in obj.padding2 { 69 testing.expect(t, b == 0) 70 } 71 } 72 73 test_using_type(t, u8(100)) 74 test_using_type(t, i8(100)) 75 test_using_type(t, true) 76 test_using_type(t, i16(100)) 77 test_using_type(t, u16(100)) 78 test_using_type(t, i32(100)) 79 test_using_type(t, u32(100)) 80 test_using_type(t, i64(100)) 81 test_using_type(t, u64(100)) 82 test_using_type(t, "hello") 83} 84 85@(private) 86field_type_deinit :: proc(field: ^Field_Type) { 87 delete(field.name) 88 delete(field.tag) 89} 90 91@(private) 92delete_field_types :: proc(field_types: []Field_Type) { 93 for &it in field_types { 94 field_type_deinit(&it) 95 } 96 97 delete(field_types) 98} 99 100@(private) 101@(require_results) 102get_type_fields :: proc($T: typeid) -> ([]Field_Type, Field_Error) { 103 out: [dynamic]Field_Type 104 struct_info := type_info_of(T) 105 for i in 0 ..< reflect.struct_field_count(T) { 106 field := reflect.struct_field_at(T, i) 107 capture, err := match_and_return_capture(`sqlite:"(.*?)"`, cast(string)field.tag) 108 if err != nil { 109 defer delete_field_types(out[:]) 110 111 return nil, fmt.tprintf( 112 "could not find sqlite tag on field '{}' of struct '{}'. err: {}", 113 field.name, 114 struct_info, 115 err, 116 ) 117 } 118 119 append( 120 &out, 121 Field_Type { 122 tag = capture, 123 name = strings.clone(field.name), 124 type = field.type, 125 offset = int(field.offset), 126 }, 127 ) 128 129 } 130 131 return out[:], nil 132} 133 134 135@(test) 136get_type_fields_test__all_ok :: proc(t: ^testing.T) { 137 S :: struct { 138 a: int `sqlite:"Foo"`, 139 b: bool `sqlite:"Bar"`, 140 c: string `sqlite:"Foobar"`, 141 } 142 143 fields, err := get_type_fields(S) 144 testing.expect(t, err == nil) 145 defer delete_field_types(fields) 146 147 testing.expect(t, fields[0].tag == "Foo") 148 testing.expect(t, fields[0].name == "a") 149 testing.expect(t, fields[0].type.id == typeid_of(int)) 150 151 testing.expect(t, fields[1].tag == "Bar") 152 testing.expect(t, fields[1].name == "b") 153 testing.expect(t, fields[1].type.id == typeid_of(bool)) 154 155 testing.expect(t, fields[2].tag == "Foobar") 156 testing.expect(t, fields[2].name == "c") 157 testing.expect(t, fields[2].type.id == typeid_of(string)) 158} 159 160 161@(test) 162get_type_fields_test__missing_tag :: proc(t: ^testing.T) { 163 S :: struct { 164 a: int `sqlite:"Foo"`, 165 b: bool, 166 c: string `sqlite:"Foobar"`, 167 } 168 169 fields, err := get_type_fields(S) 170 testing.expect(t, err != nil) 171} 172 173 174@(test) 175get_type_fields_test__malformed_tag :: proc(t: ^testing.T) { 176 S :: struct { 177 a: int `sqlite:"Foo"`, 178 b: bool `sqlit:"Bar"`, 179 c: string `sqlite:"Foobar"`, 180 } 181 182 fields, err := get_type_fields(S) 183 testing.expect(t, err != nil) 184} 185 186@(test) 187get_type_fields_test__malformed_tag_missing_quote :: proc(t: ^testing.T) { 188 S :: struct { 189 a: int `sqlite:"Foo"`, 190 b: bool `sqlite:"Bar`, 191 c: string `sqlite:"Foobar"`, 192 } 193 194 fields, err := get_type_fields(S) 195 testing.expect(t, err != nil) 196}