diff options
Diffstat (limited to 'internal/options/process.go')
-rw-r--r-- | internal/options/process.go | 109 |
1 files changed, 109 insertions, 0 deletions
diff --git a/internal/options/process.go b/internal/options/process.go new file mode 100644 index 0000000..fde73e4 --- /dev/null +++ b/internal/options/process.go @@ -0,0 +1,109 @@ +package options + +import ( + "encoding/json" + "io" + "os" + + "github.com/bcicen/jstream" + "github.com/mitchellh/mapstructure" + "github.com/pkg/errors" +) + +func ValueTypeToString(valueType jstream.ValueType) string { + switch valueType { + case jstream.Unknown: + return "unknown" + case jstream.Null: + return "null" + case jstream.String: + return "string" + case jstream.Number: + return "number" + case jstream.Boolean: + return "boolean" + case jstream.Array: + return "array" + case jstream.Object: + return "object" + } + + return "very strange" +} + +func Process(inpath string, outpath string) error { + infile, err := os.Open(inpath) + if err != nil { + return errors.WithMessagef(err, "failed to open input file %s", inpath) + } + defer infile.Close() + outfile, err := os.Create(outpath) + if err != nil { + return errors.WithMessagef(err, "failed to open output file %s", outpath) + } + if outpath != "/dev/stdout" { + defer outfile.Close() + } + + dec := jstream.NewDecoder(infile, 1).EmitKV() + var opt NixOption + ms, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{ + ErrorUnused: true, + Result: &opt, + Squash: true, + DecodeHook: mapstructure.TextUnmarshallerHookFunc(), + }) + if err != nil { + return errors.WithMessage(err, "could not create mapstructure decoder") + } + + _, err = outfile.WriteString("[\n") + if err != nil { + return errors.WithMessage(err, "could not write to output") + } + for mv := range dec.Stream() { + if err := dec.Err(); err != nil { + return errors.WithMessage(err, "could not decode JSON") + } + if mv.ValueType != jstream.Object { + return errors.Errorf("unexpected object type %s", ValueTypeToString(mv.ValueType)) + } + kv := mv.Value.(jstream.KV) + if kv.Key == "_module.args" { + continue + } + x := kv.Value.(map[string]interface{}) + x["option"] = kv.Key + + err = ms.Decode(x) + if err != nil { + return errors.WithMessagef(err, "failed to decode option %#v", x) + } + + b, err := json.MarshalIndent(opt, "", " ") + if err != nil { + return errors.WithMessagef(err, "failed to encode option %#v", opt) + } + + _, err = outfile.Write(b) + if err != nil { + return errors.WithMessage(err, "failed to write to output") + } + _, err = outfile.WriteString(",\n") + if err != nil { + return errors.WithMessage(err, "failed to write to output") + } + } + + _, err = outfile.Seek(-2, io.SeekCurrent) + if err != nil { + return errors.WithMessage(err, "could not write to output") + } + + _, err = outfile.WriteString("]\n") + if err != nil { + return errors.WithMessage(err, "could not write to output") + } + + return nil +} |