@@ -18,8 +18,9 @@ import (
18
18
//
19
19
// Maps and Programs are passed to NewMapWithOptions and NewProgramsWithOptions.
20
20
type CollectionOptions struct {
21
- Maps MapOptions
22
- Programs ProgramOptions
21
+ Maps MapOptions
22
+ Variables VariableOptions
23
+ Programs ProgramOptions
23
24
24
25
// MapReplacements takes a set of Maps that will be used instead of
25
26
// creating new ones when loading the CollectionSpec.
@@ -35,8 +36,9 @@ type CollectionOptions struct {
35
36
36
37
// CollectionSpec describes a collection.
37
38
type CollectionSpec struct {
38
- Maps map [string ]* MapSpec
39
- Programs map [string ]* ProgramSpec
39
+ Maps map [string ]* MapSpec
40
+ Variables map [string ]* VariableSpec
41
+ Programs map [string ]* ProgramSpec
40
42
41
43
// Types holds type information about Maps and Programs.
42
44
// Modifications to Types are currently undefined behaviour.
@@ -55,6 +57,7 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
55
57
56
58
cpy := CollectionSpec {
57
59
Maps : make (map [string ]* MapSpec , len (cs .Maps )),
60
+ Variables : make (map [string ]* VariableSpec , len (cs .Variables )),
58
61
Programs : make (map [string ]* ProgramSpec , len (cs .Programs )),
59
62
ByteOrder : cs .ByteOrder ,
60
63
Types : cs .Types .Copy (),
@@ -64,6 +67,10 @@ func (cs *CollectionSpec) Copy() *CollectionSpec {
64
67
cpy .Maps [name ] = spec .Copy ()
65
68
}
66
69
70
+ for name , spec := range cs .Variables {
71
+ cpy .Variables [name ] = spec .Copy ()
72
+ }
73
+
67
74
for name , spec := range cs .Programs {
68
75
cpy .Programs [name ] = spec .Copy ()
69
76
}
@@ -285,6 +292,7 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
285
292
286
293
// Support assigning Programs and Maps, lazy-loading the required objects.
287
294
assignedMaps := make (map [string ]bool )
295
+ assignedVars := make (map [string ]bool )
288
296
assignedProgs := make (map [string ]bool )
289
297
290
298
getValue := func (typ reflect.Type , name string ) (interface {}, error ) {
@@ -298,6 +306,10 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
298
306
assignedMaps [name ] = true
299
307
return loader .loadMap (name )
300
308
309
+ case reflect .TypeOf ((* Variable )(nil )):
310
+ assignedVars [name ] = true
311
+ return loader .loadVariable (name )
312
+
301
313
default :
302
314
return nil , fmt .Errorf ("unsupported type %s" , typ )
303
315
}
@@ -335,18 +347,21 @@ func (cs *CollectionSpec) LoadAndAssign(to interface{}, opts *CollectionOptions)
335
347
for m := range assignedMaps {
336
348
delete (loader .maps , m )
337
349
}
350
+ for v := range assignedVars {
351
+ delete (loader .vars , v )
352
+ }
338
353
for p := range assignedProgs {
339
354
delete (loader .programs , p )
340
355
}
341
356
342
357
return nil
343
358
}
344
359
345
- // Collection is a collection of Programs and Maps associated
346
- // with their symbols
360
+ // Collection is a collection of Programs and Maps associated with their varaibles
347
361
type Collection struct {
348
- Programs map [string ]* Program
349
- Maps map [string ]* Map
362
+ Programs map [string ]* Program
363
+ Maps map [string ]* Map
364
+ Variables map [string ]* Variable
350
365
}
351
366
352
367
// NewCollection creates a Collection from the given spec, creating and
@@ -376,6 +391,11 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
376
391
return nil , err
377
392
}
378
393
}
394
+ for varName := range spec .Variables {
395
+ if _ , err := loader .loadVariable (varName ); err != nil {
396
+ return nil , err
397
+ }
398
+ }
379
399
380
400
for progName , prog := range spec .Programs {
381
401
if prog .Type == UnspecifiedProgram {
@@ -393,20 +413,22 @@ func NewCollectionWithOptions(spec *CollectionSpec, opts CollectionOptions) (*Co
393
413
return nil , err
394
414
}
395
415
396
- // Prevent loader.cleanup from closing maps and programs.
397
- maps , progs := loader .maps , loader .programs
398
- loader .maps , loader .programs = nil , nil
416
+ // Prevent loader.cleanup from closing maps, vars and programs.
417
+ maps , vars , progs := loader .maps , loader . vars , loader .programs
418
+ loader .maps , loader .vars , loader . programs = nil , nil , nil
399
419
400
420
return & Collection {
401
421
progs ,
402
422
maps ,
423
+ vars ,
403
424
}, nil
404
425
}
405
426
406
427
type collectionLoader struct {
407
428
coll * CollectionSpec
408
429
opts * CollectionOptions
409
430
maps map [string ]* Map
431
+ vars map [string ]* Variable
410
432
programs map [string ]* Program
411
433
}
412
434
@@ -431,6 +453,7 @@ func newCollectionLoader(coll *CollectionSpec, opts *CollectionOptions) (*collec
431
453
coll ,
432
454
opts ,
433
455
make (map [string ]* Map ),
456
+ make (map [string ]* Variable ),
434
457
make (map [string ]* Program ),
435
458
}, nil
436
459
}
@@ -445,6 +468,35 @@ func (cl *collectionLoader) close() {
445
468
}
446
469
}
447
470
471
+ func (cl * collectionLoader ) loadVariable (varName string ) (* Variable , error ) {
472
+ if s := cl .vars [varName ]; s != nil {
473
+ return s , nil
474
+ }
475
+
476
+ varSpec := cl .coll .Variables [varName ]
477
+ if varSpec == nil {
478
+ return nil , fmt .Errorf ("missing variable %s" , varName )
479
+ }
480
+
481
+ m := cl .maps [varSpec .MapName ]
482
+ if m == nil {
483
+ return nil , fmt .Errorf ("map %s for variable %s not found" , varSpec .MapName , varName )
484
+ }
485
+
486
+ mc , err := m .Clone ()
487
+ if err != nil {
488
+ return nil , err
489
+ }
490
+
491
+ v , err := newVariableWithOptions (varSpec , mc , cl .opts .Variables )
492
+ if err != nil {
493
+ return nil , fmt .Errorf ("variable %v: %w" , varName , err )
494
+ }
495
+
496
+ cl .vars [varName ] = v
497
+ return v , nil
498
+ }
499
+
448
500
func (cl * collectionLoader ) loadMap (mapName string ) (* Map , error ) {
449
501
if m := cl .maps [mapName ]; m != nil {
450
502
return m , nil
@@ -722,6 +774,7 @@ func LoadCollection(file string) (*Collection, error) {
722
774
// for any successful assigns. On error `to` is left in an undefined state.
723
775
func (coll * Collection ) Assign (to interface {}) error {
724
776
assignedMaps := make (map [string ]bool )
777
+ assignedVars := make (map [string ]bool )
725
778
assignedProgs := make (map [string ]bool )
726
779
727
780
// Assign() only transfers already-loaded Maps and Programs. No extra
@@ -743,6 +796,13 @@ func (coll *Collection) Assign(to interface{}) error {
743
796
}
744
797
return nil , fmt .Errorf ("missing map %q" , name )
745
798
799
+ case reflect .TypeOf ((* Variable )(nil )):
800
+ if v := coll .Variables [name ]; v != nil {
801
+ assignedVars [name ] = true
802
+ return v , nil
803
+ }
804
+ return nil , fmt .Errorf ("missing variable %q" , name )
805
+
746
806
default :
747
807
return nil , fmt .Errorf ("unsupported type %s" , typ )
748
808
}
@@ -756,6 +816,9 @@ func (coll *Collection) Assign(to interface{}) error {
756
816
for p := range assignedProgs {
757
817
delete (coll .Programs , p )
758
818
}
819
+ for s := range assignedVars {
820
+ delete (coll .Variables , s )
821
+ }
759
822
for m := range assignedMaps {
760
823
delete (coll .Maps , m )
761
824
}
0 commit comments