mirror of
https://github.com/FiloSottile/mkcert.git
synced 2025-10-14 08:51:41 +08:00
Import howett.net/plist by its correct name
Also bumping the version to one with a go.mod.
This commit is contained in:
186
vendor/howett.net/plist/marshal.go
generated
vendored
Normal file
186
vendor/howett.net/plist/marshal.go
generated
vendored
Normal file
@@ -0,0 +1,186 @@
|
||||
package plist
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
"reflect"
|
||||
"time"
|
||||
)
|
||||
|
||||
func isEmptyValue(v reflect.Value) bool {
|
||||
switch v.Kind() {
|
||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
||||
return v.Len() == 0
|
||||
case reflect.Bool:
|
||||
return !v.Bool()
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return v.Int() == 0
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return v.Uint() == 0
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return v.Float() == 0
|
||||
case reflect.Interface, reflect.Ptr:
|
||||
return v.IsNil()
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
var (
|
||||
plistMarshalerType = reflect.TypeOf((*Marshaler)(nil)).Elem()
|
||||
textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
|
||||
timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
|
||||
)
|
||||
|
||||
func implementsInterface(val reflect.Value, interfaceType reflect.Type) (interface{}, bool) {
|
||||
if val.CanInterface() && val.Type().Implements(interfaceType) {
|
||||
return val.Interface(), true
|
||||
}
|
||||
|
||||
if val.CanAddr() {
|
||||
pv := val.Addr()
|
||||
if pv.CanInterface() && pv.Type().Implements(interfaceType) {
|
||||
return pv.Interface(), true
|
||||
}
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (p *Encoder) marshalPlistInterface(marshalable Marshaler) cfValue {
|
||||
value, err := marshalable.MarshalPlist()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return p.marshal(reflect.ValueOf(value))
|
||||
}
|
||||
|
||||
// marshalTextInterface marshals a TextMarshaler to a plist string.
|
||||
func (p *Encoder) marshalTextInterface(marshalable encoding.TextMarshaler) cfValue {
|
||||
s, err := marshalable.MarshalText()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cfString(s)
|
||||
}
|
||||
|
||||
// marshalStruct marshals a reflected struct value to a plist dictionary
|
||||
func (p *Encoder) marshalStruct(typ reflect.Type, val reflect.Value) cfValue {
|
||||
tinfo, _ := getTypeInfo(typ)
|
||||
|
||||
dict := &cfDictionary{
|
||||
keys: make([]string, 0, len(tinfo.fields)),
|
||||
values: make([]cfValue, 0, len(tinfo.fields)),
|
||||
}
|
||||
for _, finfo := range tinfo.fields {
|
||||
value := finfo.value(val)
|
||||
if !value.IsValid() || finfo.omitEmpty && isEmptyValue(value) {
|
||||
continue
|
||||
}
|
||||
dict.keys = append(dict.keys, finfo.name)
|
||||
dict.values = append(dict.values, p.marshal(value))
|
||||
}
|
||||
|
||||
return dict
|
||||
}
|
||||
|
||||
func (p *Encoder) marshalTime(val reflect.Value) cfValue {
|
||||
time := val.Interface().(time.Time)
|
||||
return cfDate(time)
|
||||
}
|
||||
|
||||
func (p *Encoder) marshal(val reflect.Value) cfValue {
|
||||
if !val.IsValid() {
|
||||
return nil
|
||||
}
|
||||
|
||||
if receiver, can := implementsInterface(val, plistMarshalerType); can {
|
||||
return p.marshalPlistInterface(receiver.(Marshaler))
|
||||
}
|
||||
|
||||
// time.Time implements TextMarshaler, but we need to store it in RFC3339
|
||||
if val.Type() == timeType {
|
||||
return p.marshalTime(val)
|
||||
}
|
||||
if val.Kind() == reflect.Ptr || (val.Kind() == reflect.Interface && val.NumMethod() == 0) {
|
||||
ival := val.Elem()
|
||||
if ival.IsValid() && ival.Type() == timeType {
|
||||
return p.marshalTime(ival)
|
||||
}
|
||||
}
|
||||
|
||||
// Check for text marshaler.
|
||||
if receiver, can := implementsInterface(val, textMarshalerType); can {
|
||||
return p.marshalTextInterface(receiver.(encoding.TextMarshaler))
|
||||
}
|
||||
|
||||
// Descend into pointers or interfaces
|
||||
if val.Kind() == reflect.Ptr || (val.Kind() == reflect.Interface && val.NumMethod() == 0) {
|
||||
val = val.Elem()
|
||||
}
|
||||
|
||||
// We got this far and still may have an invalid anything or nil ptr/interface
|
||||
if !val.IsValid() || ((val.Kind() == reflect.Ptr || val.Kind() == reflect.Interface) && val.IsNil()) {
|
||||
return nil
|
||||
}
|
||||
|
||||
typ := val.Type()
|
||||
|
||||
if typ == uidType {
|
||||
return cfUID(val.Uint())
|
||||
}
|
||||
|
||||
if val.Kind() == reflect.Struct {
|
||||
return p.marshalStruct(typ, val)
|
||||
}
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.String:
|
||||
return cfString(val.String())
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
return &cfNumber{signed: true, value: uint64(val.Int())}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
||||
return &cfNumber{signed: false, value: val.Uint()}
|
||||
case reflect.Float32:
|
||||
return &cfReal{wide: false, value: val.Float()}
|
||||
case reflect.Float64:
|
||||
return &cfReal{wide: true, value: val.Float()}
|
||||
case reflect.Bool:
|
||||
return cfBoolean(val.Bool())
|
||||
case reflect.Slice, reflect.Array:
|
||||
if typ.Elem().Kind() == reflect.Uint8 {
|
||||
bytes := []byte(nil)
|
||||
if val.CanAddr() {
|
||||
bytes = val.Bytes()
|
||||
} else {
|
||||
bytes = make([]byte, val.Len())
|
||||
reflect.Copy(reflect.ValueOf(bytes), val)
|
||||
}
|
||||
return cfData(bytes)
|
||||
} else {
|
||||
values := make([]cfValue, val.Len())
|
||||
for i, length := 0, val.Len(); i < length; i++ {
|
||||
if subpval := p.marshal(val.Index(i)); subpval != nil {
|
||||
values[i] = subpval
|
||||
}
|
||||
}
|
||||
return &cfArray{values}
|
||||
}
|
||||
case reflect.Map:
|
||||
if typ.Key().Kind() != reflect.String {
|
||||
panic(&unknownTypeError{typ})
|
||||
}
|
||||
|
||||
l := val.Len()
|
||||
dict := &cfDictionary{
|
||||
keys: make([]string, 0, l),
|
||||
values: make([]cfValue, 0, l),
|
||||
}
|
||||
for _, keyv := range val.MapKeys() {
|
||||
if subpval := p.marshal(val.MapIndex(keyv)); subpval != nil {
|
||||
dict.keys = append(dict.keys, keyv.String())
|
||||
dict.values = append(dict.values, subpval)
|
||||
}
|
||||
}
|
||||
return dict
|
||||
default:
|
||||
panic(&unknownTypeError{typ})
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user