| // Copyright (c) HashiCorp, Inc. |
| // SPDX-License-Identifier: MPL-2.0 |
| |
| package random |
| |
| import ( |
| "encoding/json" |
| "fmt" |
| |
| "github.com/mitchellh/mapstructure" |
| ) |
| |
| // serializableRules is a slice of rules that can be marshalled to JSON in an HCL format |
| type serializableRules []Rule |
| |
| // MarshalJSON in an HCL-friendly way |
| func (r serializableRules) MarshalJSON() (b []byte, err error) { |
| // Example: |
| // [ |
| // { |
| // "testrule": [ |
| // { |
| // "string": "teststring", |
| // "int": 123 |
| // } |
| // ] |
| // }, |
| // { |
| // "charset": [ |
| // { |
| // "charset": "abcde", |
| // "min-chars": 2 |
| // } |
| // ] |
| // } |
| // ] |
| data := []map[string][]map[string]interface{}{} // Totally not confusing at all |
| for _, rule := range r { |
| ruleData := map[string]interface{}{} |
| err = mapstructure.Decode(rule, &ruleData) |
| if err != nil { |
| return nil, fmt.Errorf("unable to decode rule: %w", err) |
| } |
| |
| ruleMap := map[string][]map[string]interface{}{ |
| rule.Type(): { |
| ruleData, |
| }, |
| } |
| data = append(data, ruleMap) |
| } |
| |
| b, err = json.Marshal(data) |
| return b, err |
| } |
| |
| func (r *serializableRules) UnmarshalJSON(data []byte) (err error) { |
| mapData := []map[string]interface{}{} |
| err = json.Unmarshal(data, &mapData) |
| if err != nil { |
| return err |
| } |
| rules, err := parseRules(defaultRegistry, mapData) |
| if err != nil { |
| return err |
| } |
| *r = rules |
| return nil |
| } |
| |
| type runes []rune |
| |
| func (r runes) Len() int { return len(r) } |
| func (r runes) Less(i, j int) bool { return r[i] < r[j] } |
| func (r runes) Swap(i, j int) { r[i], r[j] = r[j], r[i] } |
| |
| // MarshalJSON converts the runes to a string for smaller JSON and easier readability |
| func (r runes) MarshalJSON() (b []byte, err error) { |
| return json.Marshal(string(r)) |
| } |
| |
| // UnmarshalJSON converts a string to []rune |
| func (r *runes) UnmarshalJSON(data []byte) (err error) { |
| var str string |
| err = json.Unmarshal(data, &str) |
| if err != nil { |
| return err |
| } |
| *r = []rune(str) |
| return nil |
| } |