51 lines
1.7 KiB
Go
51 lines
1.7 KiB
Go
package resource
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"sort"
|
|
)
|
|
|
|
// CanonicalGiftConfigsJSON produces the immutable semantic bytes stored with a pinned gift entitlement.
|
|
// A resource can back more than one gift ID, so the promise contains every gift that was sendable at pin time.
|
|
func CanonicalGiftConfigsJSON(configs []GiftConfig) ([]byte, error) {
|
|
return json.Marshal(canonicalGiftConfigs(configs))
|
|
}
|
|
|
|
func GiftConfigsContentHash(configs []GiftConfig) (string, error) {
|
|
body, err := CanonicalGiftConfigsJSON(configs)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
sum := sha256.Sum256(body)
|
|
return hex.EncodeToString(sum[:]), nil
|
|
}
|
|
|
|
func canonicalGiftConfigs(configs []GiftConfig) []GiftConfig {
|
|
if len(configs) == 0 {
|
|
return nil
|
|
}
|
|
canonical := append([]GiftConfig(nil), configs...)
|
|
for index := range canonical {
|
|
canonical[index].EffectTypes = append([]string(nil), canonical[index].EffectTypes...)
|
|
sort.Strings(canonical[index].EffectTypes)
|
|
canonical[index].RegionIDs = append([]int64(nil), canonical[index].RegionIDs...)
|
|
sort.Slice(canonical[index].RegionIDs, func(left, right int) bool {
|
|
return canonical[index].RegionIDs[left] < canonical[index].RegionIDs[right]
|
|
})
|
|
canonical[index].Resource.UsageScopes = append([]string(nil), canonical[index].Resource.UsageScopes...)
|
|
sort.Strings(canonical[index].Resource.UsageScopes)
|
|
}
|
|
sort.SliceStable(canonical, func(left, right int) bool {
|
|
if canonical[left].GiftID != canonical[right].GiftID {
|
|
return canonical[left].GiftID < canonical[right].GiftID
|
|
}
|
|
if canonical[left].ResourceID != canonical[right].ResourceID {
|
|
return canonical[left].ResourceID < canonical[right].ResourceID
|
|
}
|
|
return canonical[left].PriceVersion < canonical[right].PriceVersion
|
|
})
|
|
return canonical
|
|
}
|