1 // Copyright (C) The Arvados Authors. All rights reserved.
3 // SPDX-License-Identifier: Apache-2.0
16 var prefixValue = map[string]int64{
26 "P": 1000000000000000,
28 "E": 1000000000000000000,
32 func (n *ByteSize) UnmarshalJSON(data []byte) error {
33 if len(data) == 0 || data[0] != '"' {
35 err := json.Unmarshal(data, &i)
43 err := json.Unmarshal(data, &s)
47 split := strings.LastIndexAny(s, "0123456789.+-eE") + 1
49 return fmt.Errorf("invalid byte size %q", s)
51 if s[split-1] == 'E' {
52 // We accepted an E as if it started the exponent part
53 // of a json number, but if the next char isn't +, -,
54 // or digit, then the E must have meant Exa. Instead
55 // of "4.5E"+"iB" we want "4.5"+"EiB".
59 dec := json.NewDecoder(strings.NewReader(s[:split]))
61 err = dec.Decode(&val)
68 prefix := strings.Trim(s[split:], " ")
69 if strings.HasSuffix(prefix, "B") {
70 prefix = prefix[:len(prefix)-1]
72 pval, ok := prefixValue[prefix]
74 return fmt.Errorf("invalid unit %q", strings.Trim(s[split:], " "))
76 if intval, err := val.Int64(); err == nil {
77 if pval > 1 && (intval*pval)/pval != intval {
78 return fmt.Errorf("size %q overflows int64", s)
80 *n = ByteSize(intval * pval)
82 } else if floatval, err := val.Float64(); err == nil {
83 if floatval*float64(pval) > math.MaxInt64 {
84 return fmt.Errorf("size %q overflows int64", s)
86 *n = ByteSize(int64(floatval * float64(pval)))
89 return fmt.Errorf("bug: json.Number for %q is not int64 or float64: %s", s, err)