-
Notifications
You must be signed in to change notification settings - Fork 33
/
bytesize_decoder.go
93 lines (80 loc) · 2.43 KB
/
bytesize_decoder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
Copyright 2023 The Dapr Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package metadata
import (
"fmt"
"reflect"
"github.com/mitchellh/mapstructure"
"github.com/spf13/cast"
"k8s.io/apimachinery/pkg/api/resource"
)
// ByteSize contains a quantity for a resource that is measured in bytes.
// This extends the resource.Quantity struct from k8s.io/apimachinery to add some utility methods specific for Dapr.
// Although the library from K8s supports other kinds of resource quantities, our focus is on sizes in bytes.
type ByteSize struct {
resource.Quantity
}
// NewByteSize returns a new ByteSize with a default value in bytes.
func NewByteSize(defaultValue int64) ByteSize {
return ByteSize{
Quantity: *resource.NewQuantity(defaultValue, resource.BinarySI),
}
}
// GetBytes returns the number of bytes in the quantity.
// Note: this operation is expensive, so it's recommended to cache the returned value.
func (q *ByteSize) GetBytes() (int64, error) {
if q == nil || q.IsZero() {
return 0, nil
}
val, ok := q.AsInt64()
if !ok {
return 0, fmt.Errorf("cannot get bytes from resource quantity value '%v'", q)
}
return val, nil
}
func toByteSizeHookFunc() mapstructure.DecodeHookFunc {
bytesizeType := reflect.TypeOf(ByteSize{})
bytesizePtrType := reflect.TypeOf(&ByteSize{})
return func(
f reflect.Type,
t reflect.Type,
data any,
) (any, error) {
var isPtr bool
switch t {
case bytesizeType:
// Nop
case bytesizePtrType:
isPtr = true
default:
// Not a type we support with this hook
return data, nil
}
// First, cast to string
str, err := cast.ToStringE(data)
if err != nil {
return nil, fmt.Errorf("failed to cast value to string: %w", err)
}
// Parse as quantity
q, err := resource.ParseQuantity(str)
if err != nil {
return nil, fmt.Errorf("value is not a valid quantity: %w", err)
}
// Return a pointer if desired
res := ByteSize{Quantity: q}
if isPtr {
return &res, nil
}
return res, nil
}
}