github.com/drone/go-convert@v0.0.0-20240307072510-6bd371c65e61/convert/harness/yaml/unit.go (about)

     1  // Copyright 2022 Harness, Inc.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package yaml
    16  
    17  import (
    18  	"encoding/json"
    19  	"fmt"
    20  	"strconv"
    21  	"strings"
    22  	"time"
    23  
    24  	"github.com/docker/go-units"
    25  )
    26  
    27  // BytesSize stores a human-readable size in bytes,
    28  // kibibytes, mebibytes, gibibytes, or tebibytes
    29  // (eg. "44kiB", "17MiB").
    30  type BytesSize int64
    31  
    32  // UnmarshalYAML implements yaml unmarshalling.
    33  func (b *BytesSize) UnmarshalYAML(unmarshal func(interface{}) error) error {
    34  	var intType int64
    35  	if err := unmarshal(&intType); err == nil {
    36  		*b = BytesSize(intType)
    37  		return nil
    38  	}
    39  
    40  	var stringType string
    41  	if err := unmarshal(&stringType); err != nil {
    42  		return err
    43  	}
    44  
    45  	intType, err := units.RAMInBytes(stringType)
    46  	if err == nil {
    47  		*b = BytesSize(intType)
    48  	}
    49  	return err
    50  }
    51  
    52  // MarshalJSON makes UnitBytes implement json.Marshaler
    53  func (b *BytesSize) MarshalJSON() ([]byte, error) {
    54  	return json.Marshal(b.String())
    55  }
    56  
    57  // UnmarshalJSON implements json unmarshalling.
    58  func (b *BytesSize) UnmarshalJSON(data []byte) error {
    59  	var intType int64
    60  	if err := json.Unmarshal(data, &intType); err == nil {
    61  		*b = BytesSize(intType)
    62  		return nil
    63  	}
    64  
    65  	var stringType string
    66  	if err := json.Unmarshal(data, &stringType); err != nil {
    67  		return err
    68  	}
    69  
    70  	intType, err := units.RAMInBytes(stringType)
    71  	if err == nil {
    72  		*b = BytesSize(intType)
    73  	}
    74  	return err
    75  }
    76  
    77  // String returns a human-readable size in bytes,
    78  // kibibytes, mebibytes, gibibytes, or tebibytes
    79  // (eg. "44kiB", "17MiB").
    80  func (b BytesSize) String() string {
    81  	return units.BytesSize(float64(b))
    82  }
    83  
    84  // MilliSize will convert cpus to millicpus as int64.
    85  // for instance "1" will be converted to 1000 and "100m" to 100
    86  type MilliSize int64
    87  
    88  // UnmarshalYAML implements yaml unmarshalling.
    89  func (m *MilliSize) UnmarshalYAML(unmarshal func(interface{}) error) error {
    90  	var intType int64
    91  	if err := unmarshal(&intType); err == nil {
    92  		*m = MilliSize(intType * 1000)
    93  		return nil
    94  	}
    95  
    96  	var stringType string
    97  	if err := unmarshal(&stringType); err != nil {
    98  		return err
    99  	}
   100  	if strings.HasSuffix(stringType, "m") {
   101  		i, err := strconv.ParseInt(strings.TrimSuffix(stringType, "m"), 10, 64)
   102  		if err != nil {
   103  			return err
   104  		}
   105  		*m = MilliSize(i)
   106  		return nil
   107  	}
   108  	return fmt.Errorf("cannot unmarshal cpu millis")
   109  }
   110  
   111  // UnmarshalJSON implements json unmarshalling.
   112  func (m *MilliSize) UnmarshalJSON(data []byte) error {
   113  	var intType int64
   114  	if err := json.Unmarshal(data, &intType); err == nil {
   115  		*m = MilliSize(intType * 1000)
   116  		return nil
   117  	}
   118  
   119  	var stringType string
   120  	if err := json.Unmarshal(data, &stringType); err != nil {
   121  		return err
   122  	}
   123  	if strings.HasSuffix(stringType, "m") {
   124  		i, err := strconv.ParseInt(strings.TrimSuffix(stringType, "m"), 10, 64)
   125  		if err != nil {
   126  			return err
   127  		}
   128  		*m = MilliSize(i)
   129  		return nil
   130  	}
   131  	return fmt.Errorf("cannot unmarshal %s into cpu millis", string(data))
   132  }
   133  
   134  // MarshalJSON makes implements json.Marshaler
   135  func (m *MilliSize) MarshalJSON() ([]byte, error) {
   136  	return json.Marshal(m.String())
   137  }
   138  
   139  // String returns a human-readable cpu millis,
   140  // (eg. "1000", "10").
   141  func (m MilliSize) String() string {
   142  	if m == 0 {
   143  		return "0"
   144  	} else {
   145  		return strconv.FormatInt(int64(m), 10)
   146  	}
   147  }
   148  
   149  //
   150  //
   151  //
   152  
   153  // Duration is a wrapper around time.Duration which supports correct
   154  // marshaling to YAML and JSON. In particular, it marshals into strings, which
   155  // can be used as map keys in json.
   156  type Duration struct {
   157  	time.Duration
   158  }
   159  
   160  // UnmarshalJSON implements the json.Unmarshaller interface.
   161  func (d *Duration) UnmarshalJSON(b []byte) error {
   162  	var str string
   163  	err := json.Unmarshal(b, &str)
   164  	if err != nil {
   165  		return err
   166  	}
   167  
   168  	pd, err := time.ParseDuration(str)
   169  	if err != nil {
   170  		return err
   171  	}
   172  	d.Duration = pd
   173  	return nil
   174  }
   175  
   176  // MarshalJSON implements the json.Marshaler interface.
   177  func (d Duration) MarshalJSON() ([]byte, error) {
   178  	if d.Duration == 0 {
   179  		return json.Marshal("")
   180  	}
   181  	return json.Marshal(d.Duration.String())
   182  }