| ... | ... | @@ -224,6 +224,44 @@ pub fn fromSlice(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZo |
| 224 | 224 | return value; |
| 225 | 225 | } |
| 226 | 226 | |
| 227 | test fromSlice { |
| 228 | const gpa = std.testing.allocator; |
| 229 | var arena_allocator: ArenaAllocator = .init(gpa); |
| 230 | defer arena_allocator.deinit(); |
| 231 | const arena = arena_allocator.allocator(); |
| 232 | |
| 233 | const TextureOptions = struct { |
| 234 | const AddressMode = enum { clamp, reflect, wrap, zero }; |
| 235 | address_mode: struct { u: AddressMode = .wrap, v: AddressMode = .wrap }, |
| 236 | mipmaps: bool = true, |
| 237 | premultiply: bool = true, |
| 238 | }; |
| 239 | |
| 240 | const source = |
| 241 | \\.{ |
| 242 | \\ .address_mode = .{ .u = .clamp }, |
| 243 | \\ .mipmaps = false, |
| 244 | \\} |
| 245 | ; |
| 246 | |
| 247 | var errors: Errors = .empty; |
| 248 | const options = fromSlice(TextureOptions, .{ |
| 249 | .gpa = gpa, |
| 250 | .arena = arena, |
| 251 | .source = source, |
| 252 | .errors = &errors, |
| 253 | }) catch |err| { |
| 254 | errors.log("texture_options.zon", err); |
| 255 | return err; |
| 256 | }; |
| 257 | |
| 258 | try std.testing.expectEqualDeep(TextureOptions{ |
| 259 | .address_mode = .{ .u = .clamp, .v = .wrap }, |
| 260 | .mipmaps = false, |
| 261 | .premultiply = true, |
| 262 | }, options); |
| 263 | } |
| 264 | |
| 227 | 265 | /// Like `fromSlice` but the result type may not contain pointers, allowing it to outlive |
| 228 | 266 | /// `options.arena`. |
| 229 | 267 | pub fn fromSliceNoAlloc(T: type, options: FromSliceOptions) error{ OutOfMemory, ParseZon }!T { |
| ... | ... | @@ -244,6 +282,67 @@ pub fn updateFromSlice( |
| 244 | 282 | try fromSliceInner(T, value, true, options); |
| 245 | 283 | } |
| 246 | 284 | |
| 285 | test updateFromSlice { |
| 286 | const gpa = std.testing.allocator; |
| 287 | var arena_allocator: ArenaAllocator = .init(gpa); |
| 288 | defer arena_allocator.deinit(); |
| 289 | const arena = arena_allocator.allocator(); |
| 290 | |
| 291 | const MyTextEditorConfig = struct { |
| 292 | indentation: enum { spaces, tabs }, |
| 293 | columns: []const u16, |
| 294 | dark_mode: enum { auto, dark, light }, |
| 295 | theme: []const u8, |
| 296 | }; |
| 297 | |
| 298 | const global_config = |
| 299 | \\.{ |
| 300 | \\ .indentation = .spaces, |
| 301 | \\ .columns = .{ 100 }, |
| 302 | \\ .dark_mode = .dark, |
| 303 | \\} |
| 304 | ; |
| 305 | const project_config = |
| 306 | \\.{ |
| 307 | \\ .indentation = .tabs, |
| 308 | \\} |
| 309 | ; |
| 310 | |
| 311 | var config: MyTextEditorConfig = .{ |
| 312 | .indentation = .spaces, |
| 313 | .columns = &.{}, |
| 314 | .dark_mode = .auto, |
| 315 | .theme = "default", |
| 316 | }; |
| 317 | |
| 318 | var errors: Errors = .empty; |
| 319 | updateFromSlice(MyTextEditorConfig, &config, .{ |
| 320 | .gpa = gpa, |
| 321 | .arena = arena, |
| 322 | .source = global_config, |
| 323 | .errors = &errors, |
| 324 | }) catch |err| { |
| 325 | errors.log("global_config.zon", err); |
| 326 | return err; |
| 327 | }; |
| 328 | updateFromSlice(MyTextEditorConfig, &config, .{ |
| 329 | .gpa = gpa, |
| 330 | .arena = arena, |
| 331 | .source = project_config, |
| 332 | .errors = &errors, |
| 333 | }) catch |err| { |
| 334 | errors.log("project_config.zon", err); |
| 335 | return err; |
| 336 | }; |
| 337 | |
| 338 | try std.testing.expectEqualDeep(MyTextEditorConfig{ |
| 339 | .indentation = .tabs, |
| 340 | .columns = &.{100}, |
| 341 | .dark_mode = .dark, |
| 342 | .theme = "default", |
| 343 | }, config); |
| 344 | } |
| 345 | |
| 247 | 346 | /// Like `updateFromSlice` but the `T` may not contain pointers, allowing `value` to outlive |
| 248 | 347 | /// `options.arena`. |
| 249 | 348 | pub fn updateFromSliceNoAlloc( |