package cryptparse import ( `reflect` `sync` `r00t2.io/goutils/multierr` `r00t2.io/goutils/structutils` ) /* FieldMapTlsURI returns TlsUri tu from struct, map, or slice s. If a map, the keys should be the Param* tlsUriParam contants' *values* (e.g. map[string][]string{"ignore_missing": []string{"true"}}). If a slice, it should be a slice of strings (or nested other supported type) which follow the pattern `=` where `` is one of the Param* tlsUriParam constants' *values*. Obviously in both these cases, the host/port will not be set. See the NOTE below. The default is to recurse into e.g. nested structs and sub-structs unless they are tagged with the value "-". This function operates on the struct tag `tlsUri` (e.g. `tlsUri:"-"`, `tlsUri:"ca"`, etc.). If you need to use an explicit/different struct tag name, use FieldMapTlsURIWithTag. See the struct tags on TlsFlat for an example of usage. NOTE: The host and port are not currently directly configurable via struct tags. These can be set via the SetHost, SetPort, SetPortStr, SetHostPort, and/or SetHostPortStr on the returned TlsUri. */ func FieldMapTlsURI[T any](s T) (tu *TlsUri, err error) { if tu, err = FieldMapTlsURIWithTag(s, dfltStructTag); err != nil { return } return } // FieldMapTlsURIWithTag is exactly like FieldMapTlsURI but allows specifying an explict tag name. func FieldMapTlsURIWithTag[T any](s T, tagName string,) (tu *TlsUri, err error) { var ptrVal reflect.Value var sVal reflect.Value = reflect.ValueOf(s) var sType reflect.Type = sVal.Type() var params *tlsUriParams *params = make(map[tlsUriParam][]string) if sVal.IsNil() || sVal.IsZero() || !sVal.IsValid() { return } ptrVal = sVal.Elem() if err = fieldMapTlsURIStruct(params, ptrVal, tagName); err != nil { return } // TODO return } // fieldMapTlsURIStruct parses a reflect.Value and populates params with any matching fields found. func fieldMapTlsURIStruct(params *tlsUriParams, v reflect.Value, tagName string) (err error) { var field reflect.StructField var fieldVal reflect.Value var wg sync.WaitGroup var errChan chan error var numJobs int var doneChan chan bool = make(chan bool, 1) var mErr *multierr.MultiError = multierr.NewMultiError(nil) var t reflect.Type = v.Type() var kind reflect.Kind = t.Kind() if params == nil { err = ErrReqParams return } if kind != reflect.Struct { err = ErrReqStruct return } numJobs = v.NumField() wg.Add(numJobs) errChan = make(chan error, numJobs) for i := 0; i < v.NumField(); i++ { field = t.Field(i) fieldVal = v.Field(i) go func(f reflect.StructField, fv reflect.Value) { var fErr error defer wg.Done() if fErr = fieldMapTlsURIStructField(params, f, fv, tagName); fErr != nil { errChan <- fErr return } }(field, fieldVal) } go func() { wg.Wait() close(errChan) doneChan <- true }() <-doneChan for i := 0; i < numJobs; i++ { if err = <-errChan; err != nil { mErr.AddError(err) err = nil } } if !mErr.IsEmpty() { err = mErr return } // TODO return } // fieldMapTlsURIStructField parses a single struct field. func fieldMapTlsURIStructField(params *tlsUriParams, field reflect.StructField, fv reflect.Value, tagName string) (err error) { var parsedTagOpts map[string]bool if params == nil { err = ErrReqParams return } if !fv.CanSet() { return } // Skip if explicitly instructed to do so. parsedTagOpts = structutils.TagToBoolMap(field, tagName, structutils.TagMapTrim) if parsedTagOpts["-"] { return } if fv.Kind() == reflect.Ptr { err = fieldMapTlsURIStructField(params, field, fv.Elem(), tagName) } else { err = fieldMapTlsUriValue(params, fv, tagName) } // TODO return } // fieldMapTlsUriValue is a type dispatcher for a reflected value. func fieldMapTlsUriValue(params *tlsUriParams, v reflect.Value, tagName string) (err error) { // TODO return }