|
|
@@ -1,80 +0,0 @@
|
|
|
-package badjsonmerge
|
|
|
-
|
|
|
-import (
|
|
|
- "encoding/json"
|
|
|
- "reflect"
|
|
|
-
|
|
|
- "github.com/sagernet/sing-box/common/badjson"
|
|
|
- "github.com/sagernet/sing-box/option"
|
|
|
- E "github.com/sagernet/sing/common/exceptions"
|
|
|
-)
|
|
|
-
|
|
|
-func MergeOptions(source option.Options, destination option.Options) (option.Options, error) {
|
|
|
- rawSource, err := json.Marshal(source)
|
|
|
- if err != nil {
|
|
|
- return option.Options{}, E.Cause(err, "marshal source")
|
|
|
- }
|
|
|
- rawDestination, err := json.Marshal(destination)
|
|
|
- if err != nil {
|
|
|
- return option.Options{}, E.Cause(err, "marshal destination")
|
|
|
- }
|
|
|
- rawMerged, err := MergeJSON(rawSource, rawDestination)
|
|
|
- if err != nil {
|
|
|
- return option.Options{}, E.Cause(err, "merge options")
|
|
|
- }
|
|
|
- var merged option.Options
|
|
|
- err = json.Unmarshal(rawMerged, &merged)
|
|
|
- if err != nil {
|
|
|
- return option.Options{}, E.Cause(err, "unmarshal merged options")
|
|
|
- }
|
|
|
- return merged, nil
|
|
|
-}
|
|
|
-
|
|
|
-func MergeJSON(rawSource json.RawMessage, rawDestination json.RawMessage) (json.RawMessage, error) {
|
|
|
- source, err := badjson.Decode(rawSource)
|
|
|
- if err != nil {
|
|
|
- return nil, E.Cause(err, "decode source")
|
|
|
- }
|
|
|
- destination, err := badjson.Decode(rawDestination)
|
|
|
- if err != nil {
|
|
|
- return nil, E.Cause(err, "decode destination")
|
|
|
- }
|
|
|
- merged, err := mergeJSON(source, destination)
|
|
|
- if err != nil {
|
|
|
- return nil, err
|
|
|
- }
|
|
|
- return json.Marshal(merged)
|
|
|
-}
|
|
|
-
|
|
|
-func mergeJSON(anySource any, anyDestination any) (any, error) {
|
|
|
- switch destination := anyDestination.(type) {
|
|
|
- case badjson.JSONArray:
|
|
|
- switch source := anySource.(type) {
|
|
|
- case badjson.JSONArray:
|
|
|
- destination = append(destination, source...)
|
|
|
- default:
|
|
|
- destination = append(destination, source)
|
|
|
- }
|
|
|
- return destination, nil
|
|
|
- case *badjson.JSONObject:
|
|
|
- switch source := anySource.(type) {
|
|
|
- case *badjson.JSONObject:
|
|
|
- for _, entry := range source.Entries() {
|
|
|
- oldValue, loaded := destination.Get(entry.Key)
|
|
|
- if loaded {
|
|
|
- var err error
|
|
|
- entry.Value, err = mergeJSON(entry.Value, oldValue)
|
|
|
- if err != nil {
|
|
|
- return nil, E.Cause(err, "merge object item ", entry.Key)
|
|
|
- }
|
|
|
- }
|
|
|
- destination.Put(entry.Key, entry.Value)
|
|
|
- }
|
|
|
- default:
|
|
|
- return nil, E.New("cannot merge json object into ", reflect.TypeOf(destination))
|
|
|
- }
|
|
|
- return destination, nil
|
|
|
- default:
|
|
|
- return destination, nil
|
|
|
- }
|
|
|
-}
|