package csvlocode import ( "fmt" "io/fs" "sync" "git.frostfs.info/TrueCloudLab/frostfs-locode-db/pkg/locode" ) // Prm groups the required parameters of the Table's constructor. // // All values must comply with the requirements imposed on them. // Passing incorrect parameter values will result in constructor // failure (error or panic depending on the implementation). type Prm struct { // Path to UN/LOCODE csv table. // // Must not be empty. Path string // Path to csv table of UN/LOCODE Subdivisions. // // Must not be empty. SubDivPath string // Path to a csv table with UN/LOCODE overrides. // // Optional. OverridesPath string } // Table is a descriptor of the UN/LOCODE table in csv format. // // For correct operation, Table must be created // using the constructor (New) based on the required parameters // and optional components. After successful creation, // The Table is immediately ready to work through API. type Table struct { paths []string mode fs.FileMode subDivPath string subDivOnce sync.Once mSubDiv map[subDivKey]subDivRecord overrides map[locode.LOCODE]locode.Record } const invalidPrmValFmt = "invalid parameter %s (%T):%v" func panicOnPrmValue(n string, v any) { panic(fmt.Sprintf(invalidPrmValFmt, n, v, v)) } // New creates a new instance of the Table. // // Panics if at least one value of the parameters is invalid. // // The created Table does not require additional // initialization and is completely ready for work. func New(prm Prm, opts ...Option) *Table { switch { case prm.Path == "": panicOnPrmValue("Path", prm.Path) case prm.SubDivPath == "": panicOnPrmValue("SubDivPath", prm.SubDivPath) } o := defaultOpts() for i := range opts { opts[i](o) } t := &Table{ paths: append(o.extraPaths, prm.Path), mode: o.mode, subDivPath: prm.SubDivPath, } if err := t.initOverrides(prm.OverridesPath); err != nil { panic(fmt.Errorf("init overrides: %w", err)) } return t }