go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/configutil/env.go (about)

     1  /*
     2  
     3  Copyright (c) 2023 - Present. Will Charczuk. All rights reserved.
     4  Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository.
     5  
     6  */
     7  
     8  package configutil
     9  
    10  import (
    11  	"context"
    12  	"fmt"
    13  	"strconv"
    14  	"time"
    15  )
    16  
    17  // Env returns an environment variable with a given key as a value source.
    18  func Env[T any](key string) func(context.Context) (*T, error) {
    19  	return func(ctx context.Context) (*T, error) {
    20  		output := new(T)
    21  		raw, ok := GetEnvVars(ctx)[key]
    22  		if !ok {
    23  			return nil, nil
    24  		}
    25  		if err := parseGeneric(output, raw); err != nil {
    26  			return nil, err
    27  		}
    28  		return output, nil
    29  	}
    30  }
    31  
    32  func parseGeneric(ref any, raw string) error {
    33  	switch refv := ref.(type) {
    34  	case *string:
    35  		*refv = raw
    36  		return nil
    37  	case *[]byte:
    38  		*refv = []byte(raw)
    39  		return nil
    40  	case *float64:
    41  		parsed, err := strconv.ParseFloat(raw, 64)
    42  		if err != nil {
    43  			return err
    44  		}
    45  		*refv = parsed
    46  		return nil
    47  	case *float32:
    48  		parsed, err := strconv.ParseFloat(raw, 32)
    49  		if err != nil {
    50  			return err
    51  		}
    52  		*refv = float32(parsed)
    53  		return nil
    54  	case *int:
    55  		parsed, err := strconv.Atoi(raw)
    56  		if err != nil {
    57  			return err
    58  		}
    59  		*refv = parsed
    60  		return nil
    61  	case *int16:
    62  		parsed, err := strconv.ParseInt(raw, 10, 16)
    63  		if err != nil {
    64  			return err
    65  		}
    66  		*refv = int16(parsed)
    67  		return nil
    68  	case *int32:
    69  		parsed, err := strconv.ParseInt(raw, 10, 32)
    70  		if err != nil {
    71  			return err
    72  		}
    73  		*refv = int32(parsed)
    74  		return nil
    75  	case *int64:
    76  		parsed, err := strconv.ParseInt(raw, 10, 64)
    77  		if err != nil {
    78  			return err
    79  		}
    80  		*refv = parsed
    81  		return nil
    82  	case *uint8:
    83  		parsed, err := strconv.ParseUint(raw, 10, 8)
    84  		if err != nil {
    85  			return err
    86  		}
    87  		*refv = uint8(parsed)
    88  		return nil
    89  	case *uint16:
    90  		parsed, err := strconv.ParseUint(raw, 10, 16)
    91  		if err != nil {
    92  			return err
    93  		}
    94  		*refv = uint16(parsed)
    95  		return nil
    96  	case *uint32:
    97  		parsed, err := strconv.ParseUint(raw, 10, 32)
    98  		if err != nil {
    99  			return err
   100  		}
   101  		*refv = uint32(parsed)
   102  		return nil
   103  	case *uint64:
   104  		parsed, err := strconv.ParseUint(raw, 10, 64)
   105  		if err != nil {
   106  			return err
   107  		}
   108  		*refv = parsed
   109  		return nil
   110  	case *time.Duration:
   111  		parsed, err := time.ParseDuration(raw)
   112  		if err != nil {
   113  			return err
   114  		}
   115  		*refv = parsed
   116  		return nil
   117  	default:
   118  		return fmt.Errorf("invalid parse target: %T", ref)
   119  	}
   120  }