174 lines
3.9 KiB
Go
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
|
|
}
|