categories/categories.go (60 lines of code) (raw):

// Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one // or more contributor license agreements. Licensed under the Elastic License 2.0; // you may not use this file except in compliance with the Elastic License 2.0. package categories import ( "fmt" "io" "gopkg.in/yaml.v2" ) // Category is a common structure for all kinds of categories. type Category struct { Name string Title string Parent *Category } // Categories is a list of categories. type Categories map[string]Category // ReadCategories reads the categories from a reader. func ReadCategories(r io.Reader) (Categories, error) { var categoriesFile struct { Categories map[string]struct { Title string `yaml:"title"` Subcategories map[string]struct { Title string `yaml:"title"` } `yaml:"subcategories"` } `yaml:"categories"` } dec := yaml.NewDecoder(r) err := dec.Decode(&categoriesFile) if err != nil { return nil, fmt.Errorf("failed to decode categories: %w", err) } categories := make(Categories) addCategory := func(name, title string, parent *Category) error { if _, found := categories[name]; found { return fmt.Errorf("ambiguous definition for category %q", name) } categories[name] = Category{ Name: name, Title: title, Parent: parent, } return nil } for name, category := range categoriesFile.Categories { err := addCategory(name, category.Title, nil) if err != nil { return nil, err } for subname, subcategory := range category.Subcategories { parent := categories[name] err := addCategory(subname, subcategory.Title, &parent) if err != nil { return nil, err } } } return categories, nil } // MustReadCategories reads the categories from a reader and panics if there is any error. func MustReadCategories(r io.Reader) Categories { categories, err := ReadCategories(r) if err != nil { panic(err) } return categories }