Skip to content

Commit f73644f

Browse files
committed
Implementing string performance improvements.
Let’s go faster!
1 parent 27e04d9 commit f73644f

25 files changed

+621
-83
lines changed

functions/core/alphabetical.go

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package core
55

66
import (
7-
"fmt"
87
"github.com/daveshanley/vacuum/model"
98
vacuumUtils "github.com/daveshanley/vacuum/utils"
109
"github.com/pb33f/doctor/model/high/v3"
@@ -52,8 +51,8 @@ func (a Alphabetical) RunRule(nodes []*yaml.Node, context model.RuleFunctionCont
5251
// extract a custom message
5352
message := context.Rule.Message
5453

55-
// check supplied type
56-
props := utils.ConvertInterfaceIntoStringMap(context.Options)
54+
// check supplied type - use cached options to avoid repeated interface conversions
55+
props := context.GetOptionsStringMap()
5756
if props["keyedBy"] != "" {
5857
keyedBy = props["keyedBy"]
5958
}
@@ -79,8 +78,7 @@ func (a Alphabetical) RunRule(nodes []*yaml.Node, context model.RuleFunctionCont
7978
}
8079
result := model.RuleFunctionResult{
8180
Message: vacuumUtils.SuppliedOrDefault(message,
82-
fmt.Sprintf("%s: `%s` is a map/object. %s", context.Rule.Description,
83-
node.Value, a.GetSchema().ErrorMessage)),
81+
model.GetStringTemplates().BuildTypeErrorMessage(context.Rule.Description, node.Value, "map/object", a.GetSchema().ErrorMessage)),
8482
StartNode: node,
8583
EndNode: vacuumUtils.BuildEndNode(node),
8684
Path: locatedPath,
@@ -228,9 +226,7 @@ func compareStringArray(node *yaml.Node, strArr []string,
228226
Path: locatedPath,
229227
EndNode: vacuumUtils.BuildEndNode(node),
230228
Message: vacuumUtils.SuppliedOrDefault(message,
231-
fmt.Sprintf("%s: `%s` must be placed before `%s` (alphabetical)",
232-
context.Rule.Description,
233-
strArr[x+1], strArr[x])),
229+
model.GetStringTemplates().BuildAlphabeticalMessage(context.Rule.Description, strArr[x+1], strArr[x])),
234230
}
235231
if len(allPaths) > 1 {
236232
result.Paths = allPaths
@@ -307,7 +303,8 @@ func (a Alphabetical) evaluateIntArray(node *yaml.Node, intArray []int, errmsg s
307303
Path: locatedPath,
308304
EndNode: vacuumUtils.BuildEndNode(node),
309305
Message: vacuumUtils.SuppliedOrDefault(message,
310-
fmt.Sprintf(errmsg, context.Rule.Description, intArray[x+1], intArray[x])),
306+
model.GetStringTemplates().BuildNumericalOrderingMessage(context.Rule.Description,
307+
strconv.Itoa(intArray[x+1]), strconv.Itoa(intArray[x]))),
311308
}
312309
if len(allPaths) > 1 {
313310
result.Paths = allPaths
@@ -347,8 +344,9 @@ func (a Alphabetical) evaluateFloatArray(node *yaml.Node, floatArray []float64,
347344
StartNode: node,
348345
Path: locatedPath,
349346
EndNode: vacuumUtils.BuildEndNode(node),
350-
Message: vacuumUtils.SuppliedOrDefault(message, fmt.Sprintf(errmsg,
351-
context.Rule.Description, floatArray[x+1], floatArray[x])),
347+
Message: vacuumUtils.SuppliedOrDefault(message,
348+
model.GetStringTemplates().BuildNumericalOrderingMessage(context.Rule.Description,
349+
strconv.FormatFloat(floatArray[x+1], 'g', -1, 64), strconv.FormatFloat(floatArray[x], 'g', -1, 64))),
352350
}
353351
if len(allPaths) > 1 {
354352
result.Paths = allPaths

functions/core/casing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ func (c Casing) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext) [
106106
message := context.Rule.Message
107107

108108
// check supplied type
109-
props := utils.ConvertInterfaceIntoStringMap(context.Options)
109+
props := context.GetOptionsStringMap()
110110
if props["type"] == "" {
111111
return nil
112112
}

functions/core/enumeration.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package core
55

66
import (
7-
"fmt"
87
"github.com/daveshanley/vacuum/model"
98
vacuumUtils "github.com/daveshanley/vacuum/utils"
109
"github.com/pb33f/doctor/model/high/v3"
@@ -109,8 +108,7 @@ func (e Enumeration) RunRule(nodes []*yaml.Node, context model.RuleFunctionConte
109108

110109
result := model.RuleFunctionResult{
111110
Message: vacuumUtils.SuppliedOrDefault(message,
112-
fmt.Sprintf("%s: `%s` must equal to one of: %v", ruleMessage,
113-
node.Value, values)),
111+
model.GetStringTemplates().BuildEnumValidationMessage(ruleMessage, node.Value, values)),
114112
StartNode: node,
115113
EndNode: vacuumUtils.BuildEndNode(node),
116114
Path: locatedPath,

functions/core/length.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func (l Length) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext) [
5656
if context.Options == nil {
5757
return results
5858
}
59-
if opts := utils.ConvertInterfaceIntoStringMap(context.Options); opts != nil {
59+
if opts := context.GetOptionsStringMap(); opts != nil {
6060
if v, ok := opts["min"]; ok {
6161
minVal, _ = strconv.Atoi(v)
6262
}

functions/core/pattern.go

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package core
55

66
import (
7-
"fmt"
87
"github.com/daveshanley/vacuum/model"
98
vacuumUtils "github.com/daveshanley/vacuum/utils"
109
"github.com/pb33f/doctor/model/high/v3"
@@ -48,8 +47,8 @@ func (p Pattern) GetCategory() string {
4847
// RunRule will execute the Pattern rule, based on supplied context and a supplied []*yaml.Node slice.
4948
func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext) []model.RuleFunctionResult {
5049

51-
// check supplied type
52-
props := utils.ConvertInterfaceIntoStringMap(context.Options)
50+
// check supplied type - use cached options to avoid repeated interface conversions
51+
props := context.GetOptionsStringMap()
5352

5453
if props["match"] != "" {
5554
p.match = props["match"] // TODO: there should be no state in here, clean this up.
@@ -105,7 +104,7 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
105104
}
106105
if p.match != "" {
107106
rx, err := p.getPatternFromCache(p.match, context.Rule)
108-
expPath := fmt.Sprintf("%s['%s']", pathValue, currentField)
107+
expPath := model.GetStringTemplates().BuildQuotedPath(pathValue, currentField)
109108
if err != nil {
110109
locatedObjects, lErr := context.DrDocument.LocateModel(node)
111110
locatedPath := expPath
@@ -120,8 +119,7 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
120119
}
121120
result := model.RuleFunctionResult{
122121
Message: vacuumUtils.SuppliedOrDefault(message,
123-
fmt.Sprintf("%s: `%s` cannot be compiled into a regular expression [`%s`]",
124-
ruleMessage, p.match, err.Error())),
122+
model.GetStringTemplates().BuildRegexCompileErrorMessage(ruleMessage, p.match, err.Error())),
125123
StartNode: node,
126124
EndNode: vacuumUtils.BuildEndNode(node),
127125
Path: locatedPath,
@@ -151,8 +149,7 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
151149
}
152150
result := model.RuleFunctionResult{
153151
Message: vacuumUtils.SuppliedOrDefault(message,
154-
fmt.Sprintf("%s: `%s` does not match the expression `%s`", ruleMessage,
155-
node.Value, p.match)),
152+
model.GetStringTemplates().BuildPatternMessage(ruleMessage, node.Value, p.match)),
156153
StartNode: node,
157154
EndNode: vacuumUtils.BuildEndNode(node),
158155
Path: locatedPath,
@@ -174,7 +171,7 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
174171
// not match
175172
if p.notMatch != "" {
176173
rx, err := p.getPatternFromCache(p.notMatch, context.Rule)
177-
expPath := fmt.Sprintf("%s['%s']", pathValue, currentField)
174+
expPath := model.GetStringTemplates().BuildQuotedPath(pathValue, currentField)
178175
if err != nil {
179176
locatedObjects, lErr := context.DrDocument.LocateModel(node)
180177
locatedPath := expPath
@@ -189,8 +186,7 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
189186
}
190187
result := model.RuleFunctionResult{
191188
Message: vacuumUtils.SuppliedOrDefault(message,
192-
fmt.Sprintf("%s: cannot be compiled into a regular expression [`%s`]",
193-
ruleMessage, err.Error())),
189+
model.GetStringTemplates().BuildRegexCompileErrorMessage(ruleMessage, p.notMatch, err.Error())),
194190
StartNode: node,
195191
EndNode: vacuumUtils.BuildEndNode(node),
196192
Path: locatedPath,
@@ -222,7 +218,7 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
222218

223219
result := model.RuleFunctionResult{
224220
Message: vacuumUtils.SuppliedOrDefault(message,
225-
fmt.Sprintf("%s: matches the expression `%s`", ruleMessage, p.notMatch)),
221+
model.GetStringTemplates().BuildPatternMatchMessage(ruleMessage, p.notMatch)),
226222
StartNode: node,
227223
EndNode: vacuumUtils.BuildEndNode(node),
228224
Path: locatedPath,

functions/core/truthy.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package core
55

66
import (
7-
"fmt"
87
"github.com/daveshanley/vacuum/model"
98
vacuumUtils "github.com/daveshanley/vacuum/utils"
109
"github.com/pb33f/doctor/model/high/v3"
@@ -62,7 +61,7 @@ func (t *Truthy) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
6261
fieldNodeValue.Value == "0" || fieldNodeValue.Value == "" {
6362

6463
if isArray {
65-
pathValue = fmt.Sprintf("%s[%d]", pathValue, x)
64+
pathValue = model.GetStringTemplates().BuildArrayPath(pathValue, x)
6665
}
6766

6867
if !utils.IsNodeMap(fieldNode) && !utils.IsNodeArray(fieldNodeValue) && !utils.IsNodeMap(fieldNodeValue) {
@@ -99,7 +98,7 @@ func (t *Truthy) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
9998
}
10099
if err == nil && locatedObjects != nil {
101100
for x, obj := range locatedObjects {
102-
p := fmt.Sprintf("%s.%s", obj.GenerateJSONPath(), context.RuleAction.Field)
101+
p := model.GetStringTemplates().BuildJSONPath(obj.GenerateJSONPath(), context.RuleAction.Field)
103102
if x == 0 {
104103
locatedPath = p
105104
}
@@ -109,7 +108,7 @@ func (t *Truthy) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
109108
}
110109
result := model.RuleFunctionResult{
111110
Message: vacuumUtils.SuppliedOrDefault(message,
112-
fmt.Sprintf("%s: `%s` must be set", ruleMessage, context.RuleAction.Field)),
111+
model.GetStringTemplates().BuildFieldValidationMessage(ruleMessage, context.RuleAction.Field, "set")),
113112
StartNode: node,
114113
EndNode: vacuumUtils.BuildEndNode(node),
115114
Path: locatedPath,

functions/core/xor.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
package core
55

66
import (
7-
"fmt"
87
"github.com/daveshanley/vacuum/model"
98
vacuumUtils "github.com/daveshanley/vacuum/utils"
109
"github.com/pb33f/doctor/model/high/v3"
@@ -48,8 +47,8 @@ func (x Xor) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext) []mo
4847
return nil
4948
}
5049

51-
// check supplied properties, there can only be two
52-
props := utils.ConvertInterfaceIntoStringMap(context.Options)
50+
// check supplied properties, there can only be two - use cached options
51+
props := context.GetOptionsStringMap()
5352
var properties []string
5453

5554
if len(props) <= 0 {
@@ -97,8 +96,8 @@ func (x Xor) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext) []mo
9796
}
9897
}
9998
result := model.RuleFunctionResult{
100-
Message: vacuumUtils.SuppliedOrDefault(message, fmt.Sprintf("%s: `%s` and `%s` must not be both defined or undefined",
101-
ruleMessage, properties[0], properties[1])),
99+
Message: vacuumUtils.SuppliedOrDefault(message,
100+
model.GetStringTemplates().BuildBothDefinedMessage(ruleMessage, properties[0], properties[1])),
102101
StartNode: node,
103102
EndNode: vacuumUtils.BuildEndNode(node),
104103
Path: locatedPath,

functions/openapi/component_descriptions.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
vacuumUtils "github.com/daveshanley/vacuum/utils"
1010
"github.com/pb33f/doctor/model/high/v3"
1111
"github.com/pb33f/libopenapi/datamodel/low"
12-
"github.com/pb33f/libopenapi/utils"
1312
"gopkg.in/yaml.v3"
1413
"strconv"
1514
"strings"
@@ -43,8 +42,8 @@ func (cd ComponentDescription) RunRule(_ []*yaml.Node, context model.RuleFunctio
4342

4443
var results []model.RuleFunctionResult
4544

46-
// check supplied type
47-
props := utils.ConvertInterfaceIntoStringMap(context.Options)
45+
// check supplied type - use cached options
46+
props := context.GetOptionsStringMap()
4847

4948
minWordsString := props["minWords"]
5049
minWords, _ := strconv.Atoi(minWordsString)

functions/openapi/examples_missing.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ func (em ExamplesMissing) RunRule(_ []*yaml.Node, context model.RuleFunctionCont
250250
path := prop.GenerateJSONPath()
251251
results = append(results,
252252
buildResult(vacuumUtils.SuppliedOrDefault(context.Rule.Message,
253-
fmt.Sprintf("media type schema property `%s` is missing `examples` or `example`", propName)),
253+
model.GetStringTemplates().BuildMissingExampleMessage(propName)),
254254
path,
255255
prop.KeyNode, mt.ValueNode, mt))
256256
}

functions/openapi/no_eval_descriptions.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"github.com/daveshanley/vacuum/model"
99
vacuumUtils "github.com/daveshanley/vacuum/utils"
10-
"github.com/pb33f/libopenapi/utils"
1110
"gopkg.in/yaml.v3"
1211
)
1312

@@ -45,8 +44,8 @@ func (ne NoEvalInDescriptions) RunRule(nodes []*yaml.Node, context model.RuleFun
4544

4645
var results []model.RuleFunctionResult
4746

48-
// check supplied type
49-
props := utils.ConvertInterfaceIntoStringMap(context.Options)
47+
// check supplied type - use cached options
48+
props := context.GetOptionsStringMap()
5049

5150
pattern := props["pattern"]
5251

0 commit comments

Comments
 (0)