bump(github.com/googleapis/gnostic):0c5108395e2de

Pick up performance improvements to OpenAPI serialization.
This commit is contained in:
Clayton Coleman
2017-07-31 01:24:19 -04:00
parent d8205661b7
commit 7a458730d7
18 changed files with 2099 additions and 309 deletions

View File

@@ -14,28 +14,30 @@
package compiler
// Context contains state of the compiler as it traverses a document.
type Context struct {
Parent *Context
Name string
ExtensionHandlers *[]ExtensionHandler
}
// NewContextWithExtensions returns a new object representing the compiler state
func NewContextWithExtensions(name string, parent *Context, extensionHandlers *[]ExtensionHandler) *Context {
return &Context{Name: name, Parent: parent, ExtensionHandlers: extensionHandlers}
}
// NewContext returns a new object representing the compiler state
func NewContext(name string, parent *Context) *Context {
if parent != nil {
return &Context{Name: name, Parent: parent, ExtensionHandlers: parent.ExtensionHandlers}
} else {
return &Context{Name: name, Parent: parent, ExtensionHandlers: nil}
}
return &Context{Name: name, Parent: parent, ExtensionHandlers: nil}
}
// Description returns a text description of the compiler state
func (context *Context) Description() string {
if context.Parent != nil {
return context.Parent.Description() + "." + context.Name
} else {
return context.Name
}
return context.Name
}

View File

@@ -14,29 +14,31 @@
package compiler
// basic error type
// Error represents compiler errors and their location in the document.
type Error struct {
Context *Context
Message string
}
// NewError creates an Error.
func NewError(context *Context, message string) *Error {
return &Error{Context: context, Message: message}
}
// Error returns the string value of an Error.
func (err *Error) Error() string {
if err.Context != nil {
return "ERROR " + err.Context.Description() + " " + err.Message
} else {
if err.Context == nil {
return "ERROR " + err.Message
}
return "ERROR " + err.Context.Description() + " " + err.Message
}
// container for groups of errors
// ErrorGroup is a container for groups of Error values.
type ErrorGroup struct {
Errors []error
}
// NewErrorGroupOrNil returns a new ErrorGroup for a slice of errors or nil if the slice is empty.
func NewErrorGroupOrNil(errors []error) error {
if len(errors) == 0 {
return nil

View File

@@ -29,16 +29,18 @@ import (
yaml "gopkg.in/yaml.v2"
)
// ExtensionHandler describes a binary that is called by the compiler to handle specification extensions.
type ExtensionHandler struct {
Name string
}
// HandleExtension calls a binary extension handler.
func HandleExtension(context *Context, in interface{}, extensionName string) (bool, *any.Any, error) {
handled := false
var errFromPlugin error
var outFromPlugin *any.Any
if context.ExtensionHandlers != nil && len(*(context.ExtensionHandlers)) != 0 {
if context != nil && context.ExtensionHandlers != nil && len(*(context.ExtensionHandlers)) != 0 {
for _, customAnyProtoGenerator := range *(context.ExtensionHandlers) {
outFromPlugin, errFromPlugin = customAnyProtoGenerator.handle(in, extensionName)
if outFromPlugin == nil {

View File

@@ -19,27 +19,27 @@ import (
"gopkg.in/yaml.v2"
"regexp"
"sort"
"strings"
"strconv"
)
// compiler helper functions, usually called from generated code
// UnpackMap gets a yaml.MapSlice if possible.
func UnpackMap(in interface{}) (yaml.MapSlice, bool) {
m, ok := in.(yaml.MapSlice)
if ok {
return m, ok
} else {
// do we have an empty array?
a, ok := in.([]interface{})
if ok && len(a) == 0 {
// if so, return an empty map
return yaml.MapSlice{}, ok
} else {
return nil, ok
}
return m, true
}
// do we have an empty array?
a, ok := in.([]interface{})
if ok && len(a) == 0 {
// if so, return an empty map
return yaml.MapSlice{}, true
}
return nil, false
}
// SortedKeysForMap returns the sorted keys of a yaml.MapSlice.
func SortedKeysForMap(m yaml.MapSlice) []string {
keys := make([]string, 0)
for _, item := range m {
@@ -49,6 +49,7 @@ func SortedKeysForMap(m yaml.MapSlice) []string {
return keys
}
// MapHasKey returns true if a yaml.MapSlice contains a specified key.
func MapHasKey(m yaml.MapSlice, key string) bool {
for _, item := range m {
itemKey, ok := item.Key.(string)
@@ -59,6 +60,7 @@ func MapHasKey(m yaml.MapSlice, key string) bool {
return false
}
// MapValueForKey gets the value of a map value for a specified key.
func MapValueForKey(m yaml.MapSlice, key string) interface{} {
for _, item := range m {
itemKey, ok := item.Key.(string)
@@ -69,6 +71,7 @@ func MapValueForKey(m yaml.MapSlice, key string) interface{} {
return nil
}
// ConvertInterfaceArrayToStringArray converts an array of interfaces to an array of strings, if possible.
func ConvertInterfaceArrayToStringArray(interfaceArray []interface{}) []string {
stringArray := make([]string, 0)
for _, item := range interfaceArray {
@@ -80,22 +83,7 @@ func ConvertInterfaceArrayToStringArray(interfaceArray []interface{}) []string {
return stringArray
}
func PatternMatches(pattern string, value string) bool {
// if pattern contains a subpattern like "{path}", replace it with ".*"
if pattern[0] != '^' {
subpatternPattern := regexp.MustCompile("^.*(\\{.*\\}).*$")
if matches := subpatternPattern.FindSubmatch([]byte(pattern)); matches != nil {
match := string(matches[1])
pattern = strings.Replace(pattern, match, ".*", -1)
}
}
matched, err := regexp.Match(pattern, []byte(value))
if err != nil {
panic(err)
}
return matched
}
// MissingKeysInMap identifies which keys from a list of required keys are not in a map.
func MissingKeysInMap(m yaml.MapSlice, requiredKeys []string) []string {
missingKeys := make([]string, 0)
for _, k := range requiredKeys {
@@ -106,7 +94,8 @@ func MissingKeysInMap(m yaml.MapSlice, requiredKeys []string) []string {
return missingKeys
}
func InvalidKeysInMap(m yaml.MapSlice, allowedKeys []string, allowedPatterns []string) []string {
// InvalidKeysInMap returns keys in a map that don't match a list of allowed keys and patterns.
func InvalidKeysInMap(m yaml.MapSlice, allowedKeys []string, allowedPatterns []*regexp.Regexp) []string {
invalidKeys := make([]string, 0)
for _, item := range m {
itemKey, ok := item.Key.(string)
@@ -123,7 +112,7 @@ func InvalidKeysInMap(m yaml.MapSlice, allowedKeys []string, allowedPatterns []s
if !found {
// does the key match an allowed pattern?
for _, allowedPattern := range allowedPatterns {
if PatternMatches(allowedPattern, key) {
if allowedPattern.MatchString(key) {
found = true
break
}
@@ -137,13 +126,13 @@ func InvalidKeysInMap(m yaml.MapSlice, allowedKeys []string, allowedPatterns []s
return invalidKeys
}
// describe a map (for debugging purposes)
// DescribeMap describes a map (for debugging purposes).
func DescribeMap(in interface{}, indent string) string {
description := ""
m, ok := in.(map[string]interface{})
if ok {
keys := make([]string, 0)
for k, _ := range m {
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
@@ -166,14 +155,15 @@ func DescribeMap(in interface{}, indent string) string {
return description
}
// PluralProperties returns the string "properties" pluralized.
func PluralProperties(count int) string {
if count == 1 {
return "property"
} else {
return "properties"
}
return "properties"
}
// StringArrayContainsValue returns true if a string array contains a specified value.
func StringArrayContainsValue(array []string, value string) bool {
for _, item := range array {
if item == value {
@@ -183,6 +173,7 @@ func StringArrayContainsValue(array []string, value string) bool {
return false
}
// StringArrayContainsValues returns true if a string array contains all of a list of specified values.
func StringArrayContainsValues(array []string, values []string) bool {
for _, value := range values {
if !StringArrayContainsValue(array, value) {
@@ -191,3 +182,16 @@ func StringArrayContainsValues(array []string, values []string) bool {
}
return true
}
// StringValue returns the string value of an item.
func StringValue(item interface{}) (value string, ok bool) {
value, ok = item.(string)
if ok {
return value, ok
}
intValue, ok := item.(int)
if ok {
return strconv.Itoa(intValue), true
}
return "", false
}

View File

@@ -25,29 +25,30 @@ import (
"strings"
)
var file_cache map[string][]byte
var info_cache map[string]interface{}
var fileCache map[string][]byte
var infoCache map[string]interface{}
var count int64
var VERBOSE_READER = false
var verboseReader = false
func initializeFileCache() {
if file_cache == nil {
file_cache = make(map[string][]byte, 0)
if fileCache == nil {
fileCache = make(map[string][]byte, 0)
}
}
func initializeInfoCache() {
if info_cache == nil {
info_cache = make(map[string]interface{}, 0)
if infoCache == nil {
infoCache = make(map[string]interface{}, 0)
}
}
// FetchFile gets a specified file from the local filesystem or a remote location.
func FetchFile(fileurl string) ([]byte, error) {
initializeFileCache()
bytes, ok := file_cache[fileurl]
bytes, ok := fileCache[fileurl]
if ok {
if VERBOSE_READER {
if verboseReader {
log.Printf("Cache hit %s", fileurl)
}
return bytes, nil
@@ -56,30 +57,17 @@ func FetchFile(fileurl string) ([]byte, error) {
response, err := http.Get(fileurl)
if err != nil {
return nil, err
} else {
defer response.Body.Close()
bytes, err := ioutil.ReadAll(response.Body)
if err == nil {
file_cache[fileurl] = bytes
}
return bytes, err
}
defer response.Body.Close()
bytes, err = ioutil.ReadAll(response.Body)
if err == nil {
fileCache[fileurl] = bytes
}
return bytes, err
}
// read a file and unmarshal it as a yaml.MapSlice
func ReadInfoForFile(filename string) (interface{}, error) {
initializeInfoCache()
info, ok := info_cache[filename]
if ok {
if VERBOSE_READER {
log.Printf("Cache hit info for file %s", filename)
}
return info, nil
}
if VERBOSE_READER {
log.Printf("Reading info for file %s", filename)
}
// ReadBytesForFile reads the bytes of a file.
func ReadBytesForFile(filename string) ([]byte, error) {
// is the filename a url?
fileurl, _ := url.Parse(filename)
if fileurl.Scheme != "" {
@@ -88,43 +76,51 @@ func ReadInfoForFile(filename string) (interface{}, error) {
if err != nil {
return nil, err
}
var info yaml.MapSlice
err = yaml.Unmarshal(bytes, &info)
if err != nil {
return nil, err
}
info_cache[filename] = info
return info, nil
} else {
// no, it's a local filename
bytes, err := ioutil.ReadFile(filename)
if err != nil {
log.Printf("File error: %v\n", err)
return nil, err
}
var info yaml.MapSlice
err = yaml.Unmarshal(bytes, &info)
if err != nil {
return nil, err
}
info_cache[filename] = info
return info, nil
return bytes, nil
}
// no, it's a local filename
bytes, err := ioutil.ReadFile(filename)
if err != nil {
return nil, err
}
return bytes, nil
}
// read a file and return the fragment needed to resolve a $ref
// ReadInfoFromBytes unmarshals a file as a yaml.MapSlice.
func ReadInfoFromBytes(filename string, bytes []byte) (interface{}, error) {
initializeInfoCache()
cachedInfo, ok := infoCache[filename]
if ok {
if verboseReader {
log.Printf("Cache hit info for file %s", filename)
}
return cachedInfo, nil
}
if verboseReader {
log.Printf("Reading info for file %s", filename)
}
var info yaml.MapSlice
err := yaml.Unmarshal(bytes, &info)
if err != nil {
return nil, err
}
infoCache[filename] = info
return info, nil
}
// ReadInfoForRef reads a file and return the fragment needed to resolve a $ref.
func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
initializeInfoCache()
{
info, ok := info_cache[ref]
info, ok := infoCache[ref]
if ok {
if VERBOSE_READER {
if verboseReader {
log.Printf("Cache hit for ref %s#%s", basefile, ref)
}
return info, nil
}
}
if VERBOSE_READER {
if verboseReader {
log.Printf("Reading info for ref %s#%s", basefile, ref)
}
count = count + 1
@@ -136,7 +132,11 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
} else {
filename = basefile
}
info, err := ReadInfoForFile(filename)
bytes, err := ReadBytesForFile(filename)
if err != nil {
return nil, err
}
info, err := ReadInfoFromBytes(filename, bytes)
if err != nil {
log.Printf("File error: %v\n", err)
} else {
@@ -154,7 +154,7 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
}
}
if !found {
info_cache[ref] = nil
infoCache[ref] = nil
return nil, NewError(nil, fmt.Sprintf("could not resolve %s", ref))
}
}
@@ -162,6 +162,6 @@ func ReadInfoForRef(basefile string, ref string) (interface{}, error) {
}
}
}
info_cache[ref] = info
infoCache[ref] = info
return info, nil
}