Files
TomSweeneyRedHat 711474d92e Vendor Buildah 1.10.1
As the title says, vendor Buildah v1.10.1

Signed-off-by: TomSweeneyRedHat <tsweeney@redhat.com>
2019-08-08 16:06:40 -04:00

324 lines
8.0 KiB
Go

/**
* Copyright 2014 Paul Querna
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package ffjsoninception
import (
"fmt"
"reflect"
"strings"
"github.com/pquerna/ffjson/shared"
)
var validValues []string = []string{
"FFTok_left_brace",
"FFTok_left_bracket",
"FFTok_integer",
"FFTok_double",
"FFTok_string",
"FFTok_bool",
"FFTok_null",
}
func CreateUnmarshalJSON(ic *Inception, si *StructInfo) error {
out := ""
ic.OutputImports[`fflib "github.com/pquerna/ffjson/fflib/v1"`] = true
if len(si.Fields) > 0 {
ic.OutputImports[`"bytes"`] = true
}
ic.OutputImports[`"fmt"`] = true
out += tplStr(decodeTpl["header"], header{
IC: ic,
SI: si,
})
out += tplStr(decodeTpl["ujFunc"], ujFunc{
SI: si,
IC: ic,
ValidValues: validValues,
ResetFields: ic.ResetFields,
})
ic.OutputFuncs = append(ic.OutputFuncs, out)
return nil
}
func handleField(ic *Inception, name string, typ reflect.Type, ptr bool, quoted bool) string {
return handleFieldAddr(ic, name, false, typ, ptr, quoted)
}
func handleFieldAddr(ic *Inception, name string, takeAddr bool, typ reflect.Type, ptr bool, quoted bool) string {
out := fmt.Sprintf("/* handler: %s type=%v kind=%v quoted=%t*/\n", name, typ, typ.Kind(), quoted)
umlx := typ.Implements(unmarshalFasterType) || typeInInception(ic, typ, shared.MustDecoder)
umlx = umlx || reflect.PtrTo(typ).Implements(unmarshalFasterType)
umlstd := typ.Implements(unmarshalerType) || reflect.PtrTo(typ).Implements(unmarshalerType)
out += tplStr(decodeTpl["handleUnmarshaler"], handleUnmarshaler{
IC: ic,
Name: name,
Typ: typ,
Ptr: reflect.Ptr,
TakeAddr: takeAddr || ptr,
UnmarshalJSONFFLexer: umlx,
Unmarshaler: umlstd,
})
if umlx || umlstd {
return out
}
// TODO(pquerna): generic handling of token type mismatching struct type
switch typ.Kind() {
case reflect.Int,
reflect.Int8,
reflect.Int16,
reflect.Int32,
reflect.Int64:
allowed := buildTokens(quoted, "FFTok_string", "FFTok_integer", "FFTok_null")
out += getAllowTokens(typ.Name(), allowed...)
out += getNumberHandler(ic, name, takeAddr || ptr, typ, "ParseInt")
case reflect.Uint,
reflect.Uint8,
reflect.Uint16,
reflect.Uint32,
reflect.Uint64:
allowed := buildTokens(quoted, "FFTok_string", "FFTok_integer", "FFTok_null")
out += getAllowTokens(typ.Name(), allowed...)
out += getNumberHandler(ic, name, takeAddr || ptr, typ, "ParseUint")
case reflect.Float32,
reflect.Float64:
allowed := buildTokens(quoted, "FFTok_string", "FFTok_double", "FFTok_integer", "FFTok_null")
out += getAllowTokens(typ.Name(), allowed...)
out += getNumberHandler(ic, name, takeAddr || ptr, typ, "ParseFloat")
case reflect.Bool:
ic.OutputImports[`"bytes"`] = true
ic.OutputImports[`"errors"`] = true
allowed := buildTokens(quoted, "FFTok_string", "FFTok_bool", "FFTok_null")
out += getAllowTokens(typ.Name(), allowed...)
out += tplStr(decodeTpl["handleBool"], handleBool{
Name: name,
Typ: typ,
TakeAddr: takeAddr || ptr,
})
case reflect.Ptr:
out += tplStr(decodeTpl["handlePtr"], handlePtr{
IC: ic,
Name: name,
Typ: typ,
Quoted: quoted,
})
case reflect.Array,
reflect.Slice:
out += getArrayHandler(ic, name, typ, ptr)
case reflect.String:
// Is it a json.Number?
if typ.PkgPath() == "encoding/json" && typ.Name() == "Number" {
// Fall back to json package to rely on the valid number check.
// See: https://github.com/golang/go/blob/f05c3aa24d815cd3869153750c9875e35fc48a6e/src/encoding/json/decode.go#L897
ic.OutputImports[`"encoding/json"`] = true
out += tplStr(decodeTpl["handleFallback"], handleFallback{
Name: name,
Typ: typ,
Kind: typ.Kind(),
})
} else {
out += tplStr(decodeTpl["handleString"], handleString{
IC: ic,
Name: name,
Typ: typ,
TakeAddr: takeAddr || ptr,
Quoted: quoted,
})
}
case reflect.Interface:
ic.OutputImports[`"encoding/json"`] = true
out += tplStr(decodeTpl["handleFallback"], handleFallback{
Name: name,
Typ: typ,
Kind: typ.Kind(),
})
case reflect.Map:
out += tplStr(decodeTpl["handleObject"], handleObject{
IC: ic,
Name: name,
Typ: typ,
Ptr: reflect.Ptr,
TakeAddr: takeAddr || ptr,
})
default:
ic.OutputImports[`"encoding/json"`] = true
out += tplStr(decodeTpl["handleFallback"], handleFallback{
Name: name,
Typ: typ,
Kind: typ.Kind(),
})
}
return out
}
func getArrayHandler(ic *Inception, name string, typ reflect.Type, ptr bool) string {
if typ.Kind() == reflect.Slice && typ.Elem().Kind() == reflect.Uint8 {
ic.OutputImports[`"encoding/base64"`] = true
useReflectToSet := false
if typ.Elem().Name() != "byte" {
ic.OutputImports[`"reflect"`] = true
useReflectToSet = true
}
return tplStr(decodeTpl["handleByteSlice"], handleArray{
IC: ic,
Name: name,
Typ: typ,
Ptr: reflect.Ptr,
UseReflectToSet: useReflectToSet,
})
}
if typ.Elem().Kind() == reflect.Struct && typ.Elem().Name() != "" {
goto sliceOrArray
}
if (typ.Elem().Kind() == reflect.Struct || typ.Elem().Kind() == reflect.Map) ||
typ.Elem().Kind() == reflect.Array || typ.Elem().Kind() == reflect.Slice &&
typ.Elem().Name() == "" {
ic.OutputImports[`"encoding/json"`] = true
return tplStr(decodeTpl["handleFallback"], handleFallback{
Name: name,
Typ: typ,
Kind: typ.Kind(),
})
}
sliceOrArray:
if typ.Kind() == reflect.Array {
return tplStr(decodeTpl["handleArray"], handleArray{
IC: ic,
Name: name,
Typ: typ,
IsPtr: ptr,
Ptr: reflect.Ptr,
})
}
return tplStr(decodeTpl["handleSlice"], handleArray{
IC: ic,
Name: name,
Typ: typ,
IsPtr: ptr,
Ptr: reflect.Ptr,
})
}
func getAllowTokens(name string, tokens ...string) string {
return tplStr(decodeTpl["allowTokens"], allowTokens{
Name: name,
Tokens: tokens,
})
}
func getNumberHandler(ic *Inception, name string, takeAddr bool, typ reflect.Type, parsefunc string) string {
return tplStr(decodeTpl["handlerNumeric"], handlerNumeric{
IC: ic,
Name: name,
ParseFunc: parsefunc,
TakeAddr: takeAddr,
Typ: typ,
})
}
func getNumberSize(typ reflect.Type) string {
return fmt.Sprintf("%d", typ.Bits())
}
func getType(ic *Inception, name string, typ reflect.Type) string {
s := typ.Name()
if typ.PkgPath() != "" && typ.PkgPath() != ic.PackagePath {
path := removeVendor(typ.PkgPath())
ic.OutputImports[`"`+path+`"`] = true
s = typ.String()
}
if s == "" {
return typ.String()
}
return s
}
// removeVendor removes everything before and including a '/vendor/'
// substring in the package path.
// This is needed becuase that full path can't be used in the
// import statement.
func removeVendor(path string) string {
i := strings.Index(path, "/vendor/")
if i == -1 {
return path
}
return path[i+8:]
}
func buildTokens(containsOptional bool, optional string, required ...string) []string {
if containsOptional {
return append(required, optional)
}
return required
}
func unquoteField(quoted bool) string {
// The outer quote of a string is already stripped out by
// the lexer. We need to check if the inner string is also
// quoted. If so, we will decode it as json string. If decoding
// fails, we will use the original string
if quoted {
return `
unquoted, ok := fflib.UnquoteBytes(outBuf)
if ok {
outBuf = unquoted
}
`
}
return ""
}
func getTmpVarFor(name string) string {
return "tmp" + strings.Replace(strings.Title(name), ".", "", -1)
}