1
0
go_cryptparse/funcs_fieldmap_tlsuri.go
2025-01-25 16:11:19 -05:00

174 lines
3.9 KiB
Go

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 `<key>=<value>` where `<key>` 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
}