diff options
author | Ondrej Fabry <ofabry@cisco.com> | 2018-08-15 12:59:25 +0200 |
---|---|---|
committer | Ondrej Fabry <ofabry@cisco.com> | 2018-08-16 15:03:29 +0200 |
commit | a3bb834db727a3ac9a1ffcfeae9265e5dead851f (patch) | |
tree | 6ffe64d2dd78a4c3434c2889dd7582b74619fe2b /cmd/binapi-generator/generator.go | |
parent | da815585c3f75c4ac073b0766dd668abf83844d8 (diff) |
Refactor GoVPP
Squashed commit of the following:
commit 348930db31575e9f59b3834d9fec07411f011e05
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 15 11:30:13 2018 +0200
Use debug level for log about different context
commit 9fc963c559cea67a41b85c6cdadc322fb3b1fc7c
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 15 11:22:03 2018 +0200
Remove annoying logs and add env vars for debugging
commit fdc9fd624d13feadb602e0d03d58f8a44b7a565f
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 15 11:18:47 2018 +0200
Fix printing unknown VPPApiError
commit 8f968be36a91de4d4a8ea17593ba314f82aa9583
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Tue Aug 14 17:25:10 2018 +0200
Refactor entire GoVPP
- fix some cases with inconsistent VPP messages, causing messages
to be incorrectly identified as event or request
- simplify API, remove direct access to internal Go channels
- add module name with message to registration of messages
- start watching filesystem only when vpe-api file does not exist
- simplify code in message codec and remove unneeded parts
- retrieve IDs of all registered messages after connect to VPP
- define fallback for control ping in core to avoid duplicate registration
- add SetLogLevel function to set logger level more easily
- remove lot of unused code
commit 34dd1b7e10ef0324aa8c4e4cc42375bd6021c6cb
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Mon Aug 13 11:29:54 2018 +0200
Rename VnetError to VPPApiError
commit c6549d6f77847a1367a12ff47fb716e2955e973a
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Mon Aug 13 10:23:43 2018 +0200
Fix examples and regenerate binapi
commit 4612e36b416779771f5efab4fc654c2766d2cb1c
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Mon Aug 13 09:51:22 2018 +0200
Add parsing and generation for services
commit ac9c5280c5aa27e325f327609e2364cc66f3723f
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Fri Aug 10 14:30:15 2018 +0200
Fix exit status on error and add continue-onerror flag
commit 9b3f4ef9fc7c8c62037fa107085eae18a8725314
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 15:20:56 2018 +0200
Return VnetError when Retval != 0
commit 8fd21a907b5e628ec4d2026215b83d15da96c297
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 14:59:05 2018 +0200
Add all missing errors from api_errno.h
commit 08450f288d3046ebaecf40203174ae342a07f1eb
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 14:29:27 2018 +0200
Update README
commit d8dced0728dd62243539be741868fb7d9b8de4cc
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:59:59 2018 +0200
Regenerate vpe in core
commit 254da7592cdbf634cf7aa46ae36ce7bb6d4ee555
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:37:00 2018 +0200
Add VnetError type for Retvals
commit 4475c1087fb53ab4c788e530bc7fef7cfc89d2cd
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:36:07 2018 +0200
Add registration API
commit 892a3ea5a2c703e2f7c29331663f6a6fa706bff5
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 13:30:43 2018 +0200
Generate registration for messages and check all IDs on connect
commit 389ed03b6e7082260281866c3449d72d72347c99
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:32:41 2018 +0200
Show error for empty adapter (on Darwin/Windows)
commit ef1ea040d656ade64242432dc5f06810ed8dcde6
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:31:37 2018 +0200
Improve logged info
commit d4adae3b14ed54c8d693060dd857fa9ba5ec8e06
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:27:48 2018 +0200
Update examples
commit 63921e1346014701a22639a2611129563bb1eb78
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Thu Aug 9 11:02:56 2018 +0200
Generate unions and fix some issues
- add comments between sections
- define structs on single line if it has no fields
- generate unions with setters/getters for each field
- fix detection of message type
commit 6ab3e3fa590b245898306a6ffaf32c7721eab60c
Author: Ondrej Fabry <ofabry@cisco.com>
Date: Wed Aug 8 15:37:10 2018 +0200
Refactor binapi-generator
- split JSON parsing from code generation
- parse and generate enums
- parse unions (no generation yet)
- change output file suffix to '.ba.go'
- cleanup and simplify code
- split code into files
- add flag for debug mode
Change-Id: I58f685e0d4c7a38e9a7b6ea0a1f47792d95d7399
Signed-off-by: Ondrej Fabry <ofabry@cisco.com>
Diffstat (limited to 'cmd/binapi-generator/generator.go')
-rw-r--r-- | cmd/binapi-generator/generator.go | 660 |
1 files changed, 0 insertions, 660 deletions
diff --git a/cmd/binapi-generator/generator.go b/cmd/binapi-generator/generator.go deleted file mode 100644 index 15f6164..0000000 --- a/cmd/binapi-generator/generator.go +++ /dev/null @@ -1,660 +0,0 @@ -// Copyright (c) 2017 Cisco and/or its affiliates. -// -// 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 main - -import ( - "bufio" - "bytes" - "encoding/json" - "errors" - "flag" - "fmt" - "io" - "io/ioutil" - "os" - "os/exec" - "path/filepath" - "strings" - "unicode" - - "github.com/bennyscetbun/jsongo" -) - -var ( - inputFile = flag.String("input-file", "", "Input JSON file.") - inputDir = flag.String("input-dir", ".", "Input directory with JSON files.") - outputDir = flag.String("output-dir", ".", "Output directory where package folders will be generated.") - includeAPIVer = flag.Bool("include-apiver", false, "Wether to include VlAPIVersion in generated file.") -) - -// MessageType represents the type of a VPP message. -type messageType int - -const ( - requestMessage messageType = iota // VPP request message - replyMessage // VPP reply message - eventMessage // VPP event message - otherMessage // other VPP message -) - -const ( - apiImportPath = "git.fd.io/govpp.git/api" // import path of the govpp API - inputFileExt = ".json" // filename extension of files that should be processed as the input -) - -// context is a structure storing details of a particular code generation task -type context struct { - inputFile string // file with input JSON data - inputData []byte // contents of the input file - inputBuff *bytes.Buffer // contents of the input file currently being read - inputLine int // currently processed line in the input file - outputFile string // file with output data - packageName string // name of the Go package being generated - packageDir string // directory where the package source files are located - types map[string]string // map of the VPP typedef names to generated Go typedef names -} - -func main() { - flag.Parse() - - if *inputFile == "" && *inputDir == "" { - fmt.Fprintln(os.Stderr, "ERROR: input-file or input-dir must be specified") - os.Exit(1) - } - - var err, tmpErr error - if *inputFile != "" { - // process one input file - err = generateFromFile(*inputFile, *outputDir) - if err != nil { - fmt.Fprintf(os.Stderr, "ERROR: code generation from %s failed: %v\n", *inputFile, err) - } - } else { - // process all files in specified directory - files, err := getInputFiles(*inputDir) - if err != nil { - fmt.Fprintf(os.Stderr, "ERROR: code generation failed: %v\n", err) - } - for _, file := range files { - tmpErr = generateFromFile(file, *outputDir) - if tmpErr != nil { - fmt.Fprintf(os.Stderr, "ERROR: code generation from %s failed: %v\n", file, err) - err = tmpErr // remember that the error occurred - } - } - } - if err != nil { - os.Exit(1) - } -} - -// getInputFiles returns all input files located in specified directory -func getInputFiles(inputDir string) ([]string, error) { - files, err := ioutil.ReadDir(inputDir) - if err != nil { - return nil, fmt.Errorf("reading directory %s failed: %v", inputDir, err) - } - res := make([]string, 0) - for _, f := range files { - if strings.HasSuffix(f.Name(), inputFileExt) { - res = append(res, inputDir+"/"+f.Name()) - } - } - return res, nil -} - -// generateFromFile generates Go bindings from one input JSON file -func generateFromFile(inputFile, outputDir string) error { - ctx, err := getContext(inputFile, outputDir) - if err != nil { - return err - } - // read the file - ctx.inputData, err = readFile(inputFile) - if err != nil { - return err - } - - // parse JSON - jsonRoot, err := parseJSON(ctx.inputData) - if err != nil { - return err - } - - // create output directory - err = os.MkdirAll(ctx.packageDir, 0777) - if err != nil { - return fmt.Errorf("creating output directory %s failed: %v", ctx.packageDir, err) - } - - // open output file - f, err := os.Create(ctx.outputFile) - defer f.Close() - if err != nil { - return fmt.Errorf("creating output file %s failed: %v", ctx.outputFile, err) - } - w := bufio.NewWriter(f) - - // generate Go package code - err = generatePackage(ctx, w, jsonRoot) - if err != nil { - return err - } - - // go format the output file (non-fatal if fails) - exec.Command("gofmt", "-w", ctx.outputFile).Run() - - return nil -} - -// getContext returns context details of the code generation task -func getContext(inputFile, outputDir string) (*context, error) { - if !strings.HasSuffix(inputFile, inputFileExt) { - return nil, fmt.Errorf("invalid input file name %s", inputFile) - } - - ctx := &context{inputFile: inputFile} - inputFileName := filepath.Base(inputFile) - - ctx.packageName = inputFileName[0:strings.Index(inputFileName, ".")] - if ctx.packageName == "interface" { - // 'interface' cannot be a package name, it is a go keyword - ctx.packageName = "interfaces" - } - - ctx.packageDir = outputDir + "/" + ctx.packageName + "/" - ctx.outputFile = ctx.packageDir + ctx.packageName + ".go" - - return ctx, nil -} - -// readFile reads content of a file into memory -func readFile(inputFile string) ([]byte, error) { - - inputData, err := ioutil.ReadFile(inputFile) - - if err != nil { - return nil, fmt.Errorf("reading data from file failed: %v", err) - } - - return inputData, nil -} - -// parseJSON parses a JSON data into an in-memory tree -func parseJSON(inputData []byte) (*jsongo.JSONNode, error) { - root := jsongo.JSONNode{} - - err := json.Unmarshal(inputData, &root) - if err != nil { - return nil, fmt.Errorf("JSON unmarshall failed: %v", err) - } - - return &root, nil - -} - -// generatePackage generates Go code of a package from provided JSON -func generatePackage(ctx *context, w *bufio.Writer, jsonRoot *jsongo.JSONNode) error { - // generate file header - generatePackageHeader(ctx, w, jsonRoot) - - // generate data types - ctx.inputBuff = bytes.NewBuffer(ctx.inputData) - ctx.inputLine = 0 - ctx.types = make(map[string]string) - types := jsonRoot.Map("types") - for i := 0; i < types.Len(); i++ { - typ := types.At(i) - err := generateMessage(ctx, w, typ, true) - if err != nil { - return err - } - } - - // generate messages - ctx.inputBuff = bytes.NewBuffer(ctx.inputData) - ctx.inputLine = 0 - messages := jsonRoot.Map("messages") - for i := 0; i < messages.Len(); i++ { - msg := messages.At(i) - err := generateMessage(ctx, w, msg, false) - if err != nil { - return err - } - } - - // flush the data: - err := w.Flush() - if err != nil { - return fmt.Errorf("flushing data to %s failed: %v", ctx.outputFile, err) - } - - return nil -} - -// generateMessage generates Go code of one VPP message encoded in JSON into provided writer -func generateMessage(ctx *context, w io.Writer, msg *jsongo.JSONNode, isType bool) error { - if msg.Len() == 0 || msg.At(0).GetType() != jsongo.TypeValue { - return errors.New("invalid JSON for message specified") - } - - msgName, ok := msg.At(0).Get().(string) - if !ok { - return fmt.Errorf("invalid JSON for message specified, message name is %T, not a string", msg.At(0).Get()) - } - structName := camelCaseName(strings.Title(msgName)) - - // generate struct fields into the slice & determine message type - fields := make([]string, 0) - msgType := otherMessage - wasClientIndex := false - for j := 0; j < msg.Len(); j++ { - if jsongo.TypeArray == msg.At(j).GetType() { - fld := msg.At(j) - if !isType { - // determine whether ths is a request / reply / other message - fieldName, ok := fld.At(1).Get().(string) - if ok { - if j == 2 { - if fieldName == "client_index" { - // "client_index" as the second member, this might be an event message or a request - msgType = eventMessage - wasClientIndex = true - } else if fieldName == "context" { - // reply needs "context" as the second member - msgType = replyMessage - } - } else if j == 3 { - if wasClientIndex && fieldName == "context" { - // request needs "client_index" as the second member and "context" as the third member - msgType = requestMessage - } - } - } - } - err := processMessageField(ctx, &fields, fld, isType) - if err != nil { - return err - } - } - } - - // generate struct comment - generateMessageComment(ctx, w, structName, msgName, isType) - - // generate struct header - fmt.Fprintln(w, "type", structName, "struct {") - - // print out the fields - for _, field := range fields { - fmt.Fprintln(w, field) - } - - // generate end of the struct - fmt.Fprintln(w, "}") - - // generate name getter - if isType { - generateTypeNameGetter(w, structName, msgName) - } else { - generateMessageNameGetter(w, structName, msgName) - } - - // generate message type getter method - if !isType { - generateMessageTypeGetter(w, structName, msgType) - } - - // generate CRC getter - crcIf := msg.At(msg.Len() - 1).At("crc").Get() - if crc, ok := crcIf.(string); ok { - generateCrcGetter(w, structName, crc) - } - - // generate message factory - if !isType { - generateMessageFactory(w, structName) - } - - // if this is a type, save it in the map for later use - if isType { - ctx.types[fmt.Sprintf("vl_api_%s_t", msgName)] = structName - } - - return nil -} - -// processMessageField process JSON describing one message field into Go code emitted into provided slice of message fields -func processMessageField(ctx *context, fields *[]string, fld *jsongo.JSONNode, isType bool) error { - if fld.Len() < 2 || fld.At(0).GetType() != jsongo.TypeValue || fld.At(1).GetType() != jsongo.TypeValue { - return errors.New("invalid JSON for message field specified") - } - fieldVppType, ok := fld.At(0).Get().(string) - if !ok { - return fmt.Errorf("invalid JSON for message specified, field type is %T, not a string", fld.At(0).Get()) - } - fieldName, ok := fld.At(1).Get().(string) - if !ok { - return fmt.Errorf("invalid JSON for message specified, field name is %T, not a string", fld.At(1).Get()) - } - - // skip internal fields - fieldNameLower := strings.ToLower(fieldName) - if fieldNameLower == "crc" || fieldNameLower == "_vl_msg_id" { - return nil - } - if !isType && len(*fields) == 0 && (fieldNameLower == "client_index" || fieldNameLower == "context") { - return nil - } - - fieldName = strings.TrimPrefix(fieldName, "_") - fieldName = camelCaseName(strings.Title(fieldName)) - - fieldStr := "" - isArray := false - arraySize := 0 - - fieldStr += "\t" + fieldName + " " - if fld.Len() > 2 { - isArray = true - arraySize = int(fld.At(2).Get().(float64)) - fieldStr += "[]" - } - - dataType := translateVppType(ctx, fieldVppType, isArray) - fieldStr += dataType - - if isArray { - if arraySize == 0 { - // variable sized array - if fld.Len() > 3 { - // array size is specified by another field - arraySizeField := string(fld.At(3).Get().(string)) - arraySizeField = camelCaseName(strings.Title(arraySizeField)) - // find & update the field that specifies the array size - for i, f := range *fields { - if strings.Contains(f, fmt.Sprintf("\t%s ", arraySizeField)) { - (*fields)[i] += fmt.Sprintf("\t`struc:\"sizeof=%s\"`", fieldName) - } - } - } - } else { - // fixed size array - fieldStr += fmt.Sprintf("\t`struc:\"[%d]%s\"`", arraySize, dataType) - } - } - - *fields = append(*fields, fieldStr) - return nil -} - -// generatePackageHeader generates package header into provider writer -func generatePackageHeader(ctx *context, w io.Writer, rootNode *jsongo.JSONNode) { - fmt.Fprintln(w, "// Code generated by govpp binapi-generator DO NOT EDIT.") - fmt.Fprintln(w, "// Package "+ctx.packageName+" represents the VPP binary API of the '"+ctx.packageName+"' VPP module.") - fmt.Fprintln(w, "// Generated from '"+ctx.inputFile+"'") - - fmt.Fprintln(w, "package "+ctx.packageName) - - fmt.Fprintln(w, "import \""+apiImportPath+"\"") - fmt.Fprintln(w) - - vlAPIVersion := rootNode.Map("vl_api_version").Get() - if *includeAPIVer { - fmt.Fprintln(w, "// VlApiVersion contains version of the API.") - fmt.Fprintln(w, "const VlAPIVersion = ", vlAPIVersion) - fmt.Fprintln(w) - } -} - -// generateMessageComment generates comment for a message into provider writer -func generateMessageComment(ctx *context, w io.Writer, structName string, msgName string, isType bool) { - fmt.Fprintln(w) - if isType { - fmt.Fprintln(w, "// "+structName+" represents the VPP binary API data type '"+msgName+"'.") - } else { - fmt.Fprintln(w, "// "+structName+" represents the VPP binary API message '"+msgName+"'.") - } - - // print out the source of the generated message - the JSON - msgFound := false - msgTitle := "\"" + msgName + "\"," - var msgIndent int - for { - lineBuff, err := ctx.inputBuff.ReadBytes('\n') - if err != nil { - break - } - ctx.inputLine++ - line := string(lineBuff) - - if !msgFound { - msgIndent = strings.Index(line, msgTitle) - if msgIndent > -1 { - prefix := line[:msgIndent] - suffix := line[msgIndent+len(msgTitle):] - // If no other non-whitespace character then we are at the message header. - if strings.IndexFunc(prefix, isNotSpace) == -1 && strings.IndexFunc(suffix, isNotSpace) == -1 { - fmt.Fprintf(w, "// Generated from '%s', line %d:\n", ctx.inputFile, ctx.inputLine) - fmt.Fprintln(w, "//") - fmt.Fprint(w, "//", line) - msgFound = true - } - } - } else { - if strings.IndexFunc(line, isNotSpace) < msgIndent { - break // end of the message in JSON - } - fmt.Fprint(w, "//", line) - } - } - fmt.Fprintln(w, "//") -} - -// generateMessageNameGetter generates getter for original VPP message name into the provider writer -func generateMessageNameGetter(w io.Writer, structName string, msgName string) { - fmt.Fprintln(w, "func (*"+structName+") GetMessageName() string {") - fmt.Fprintln(w, "\treturn \""+msgName+"\"") - fmt.Fprintln(w, "}") -} - -// generateTypeNameGetter generates getter for original VPP type name into the provider writer -func generateTypeNameGetter(w io.Writer, structName string, msgName string) { - fmt.Fprintln(w, "func (*"+structName+") GetTypeName() string {") - fmt.Fprintln(w, "\treturn \""+msgName+"\"") - fmt.Fprintln(w, "}") -} - -// generateMessageTypeGetter generates message factory for the generated message into the provider writer -func generateMessageTypeGetter(w io.Writer, structName string, msgType messageType) { - fmt.Fprintln(w, "func (*"+structName+") GetMessageType() api.MessageType {") - if msgType == requestMessage { - fmt.Fprintln(w, "\treturn api.RequestMessage") - } else if msgType == replyMessage { - fmt.Fprintln(w, "\treturn api.ReplyMessage") - } else if msgType == eventMessage { - fmt.Fprintln(w, "\treturn api.EventMessage") - } else { - fmt.Fprintln(w, "\treturn api.OtherMessage") - } - fmt.Fprintln(w, "}") -} - -// generateCrcGetter generates getter for CRC checksum of the message definition into the provider writer -func generateCrcGetter(w io.Writer, structName string, crc string) { - crc = strings.TrimPrefix(crc, "0x") - fmt.Fprintln(w, "func (*"+structName+") GetCrcString() string {") - fmt.Fprintln(w, "\treturn \""+crc+"\"") - fmt.Fprintln(w, "}") -} - -// generateMessageFactory generates message factory for the generated message into the provider writer -func generateMessageFactory(w io.Writer, structName string) { - fmt.Fprintln(w, "func New"+structName+"() api.Message {") - fmt.Fprintln(w, "\treturn &"+structName+"{}") - fmt.Fprintln(w, "}") -} - -// translateVppType translates the VPP data type into Go data type -func translateVppType(ctx *context, vppType string, isArray bool) string { - // basic types - switch vppType { - case "u8": - if isArray { - return "byte" - } - return "uint8" - case "i8": - return "int8" - case "u16": - return "uint16" - case "i16": - return "int16" - case "u32": - return "uint32" - case "i32": - return "int32" - case "u64": - return "uint64" - case "i64": - return "int64" - case "f64": - return "float64" - } - - // typedefs - typ, ok := ctx.types[vppType] - if ok { - return typ - } - - panic(fmt.Sprintf("Unknown VPP type %s", vppType)) -} - -// camelCaseName returns correct name identifier (camelCase). -func camelCaseName(name string) (should string) { - // Fast path for simple cases: "_" and all lowercase. - if name == "_" { - return name - } - allLower := true - for _, r := range name { - if !unicode.IsLower(r) { - allLower = false - break - } - } - if allLower { - return name - } - - // Split camelCase at any lower->upper transition, and split on underscores. - // Check each word for common initialisms. - runes := []rune(name) - w, i := 0, 0 // index of start of word, scan - for i+1 <= len(runes) { - eow := false // whether we hit the end of a word - if i+1 == len(runes) { - eow = true - } else if runes[i+1] == '_' { - // underscore; shift the remainder forward over any run of underscores - eow = true - n := 1 - for i+n+1 < len(runes) && runes[i+n+1] == '_' { - n++ - } - - // Leave at most one underscore if the underscore is between two digits - if i+n+1 < len(runes) && unicode.IsDigit(runes[i]) && unicode.IsDigit(runes[i+n+1]) { - n-- - } - - copy(runes[i+1:], runes[i+n+1:]) - runes = runes[:len(runes)-n] - } else if unicode.IsLower(runes[i]) && !unicode.IsLower(runes[i+1]) { - // lower->non-lower - eow = true - } - i++ - if !eow { - continue - } - - // [w,i) is a word. - word := string(runes[w:i]) - if u := strings.ToUpper(word); commonInitialisms[u] { - // Keep consistent case, which is lowercase only at the start. - if w == 0 && unicode.IsLower(runes[w]) { - u = strings.ToLower(u) - } - // All the common initialisms are ASCII, - // so we can replace the bytes exactly. - copy(runes[w:], []rune(u)) - } else if w > 0 && strings.ToLower(word) == word { - // already all lowercase, and not the first word, so uppercase the first character. - runes[w] = unicode.ToUpper(runes[w]) - } - w = i - } - return string(runes) -} - -// isNotSpace returns true if the rune is NOT a whitespace character. -func isNotSpace(r rune) bool { - return !unicode.IsSpace(r) -} - -// commonInitialisms is a set of common initialisms that need to stay in upper case. -var commonInitialisms = map[string]bool{ - "ACL": true, - "API": true, - "ASCII": true, - "CPU": true, - "CSS": true, - "DNS": true, - "EOF": true, - "GUID": true, - "HTML": true, - "HTTP": true, - "HTTPS": true, - "ID": true, - "IP": true, - "ICMP": true, - "JSON": true, - "LHS": true, - "QPS": true, - "RAM": true, - "RHS": true, - "RPC": true, - "SLA": true, - "SMTP": true, - "SQL": true, - "SSH": true, - "TCP": true, - "TLS": true, - "TTL": true, - "UDP": true, - "UI": true, - "UID": true, - "UUID": true, - "URI": true, - "URL": true, - "UTF8": true, - "VM": true, - "XML": true, - "XMPP": true, - "XSRF": true, - "XSS": true, -} |