Skip to content

Commit c9909ff

Browse files
mromaszewiczclaude
andauthored
fix: strip style prefix for label/matrix primitive parameters (#99) (#100)
BindStyledParameterWithOptions passed the raw styled value directly to BindStringToObject for primitive types, without first removing the style prefix. This caused label (leading ".") and matrix (";param=") styles to fail with parse errors for non-struct, non-slice destinations. Route primitive values through splitStyledParameter — the same function already used by the struct and slice paths — so the prefix is stripped before binding. Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 09a43f0 commit c9909ff

File tree

2 files changed

+58
-2
lines changed

2 files changed

+58
-2
lines changed

bindparam.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,16 @@ func BindStyledParameterWithOptions(style string, paramName string, value string
155155
return bindSplitPartsToDestinationArray(parts, dest)
156156
}
157157

158-
// Try to bind the remaining types as a base type.
159-
return BindStringToObject(value, dest)
158+
// For primitive types, we still need to strip style prefixes (e.g. label's
159+
// leading "." or matrix's ";paramName=") before binding.
160+
parts, err := splitStyledParameter(style, opts.Explode, false, paramName, value)
161+
if err != nil {
162+
return fmt.Errorf("error splitting parameter '%s': %w", paramName, err)
163+
}
164+
if len(parts) != 1 {
165+
return fmt.Errorf("parameter '%s': expected single value, got %d parts", paramName, len(parts))
166+
}
167+
return BindStringToObject(parts[0], dest)
160168
}
161169

162170
// This is a complex set of operations, but each given parameter style can be

bindparam_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,6 +1116,54 @@ func TestRoundTripQueryParameter(t *testing.T) {
11161116
})
11171117
}
11181118

1119+
func TestBindStyledParameterWithOptions_LabelPrimitive(t *testing.T) {
1120+
tests := []struct {
1121+
name string
1122+
explode bool
1123+
value string
1124+
want int32
1125+
}{
1126+
{"non-exploded", false, ".5", 5},
1127+
{"exploded", true, ".5", 5},
1128+
}
1129+
for _, tt := range tests {
1130+
t.Run(tt.name, func(t *testing.T) {
1131+
var dest int32
1132+
err := BindStyledParameterWithOptions("label", "param", tt.value, &dest, BindStyledParameterOptions{
1133+
ParamLocation: ParamLocationPath,
1134+
Explode: tt.explode,
1135+
Required: true,
1136+
})
1137+
require.NoError(t, err)
1138+
assert.Equal(t, tt.want, dest)
1139+
})
1140+
}
1141+
}
1142+
1143+
func TestBindStyledParameterWithOptions_MatrixPrimitive(t *testing.T) {
1144+
tests := []struct {
1145+
name string
1146+
explode bool
1147+
value string
1148+
want int32
1149+
}{
1150+
{"non-exploded", false, ";param=5", 5},
1151+
{"exploded", true, ";param=5", 5},
1152+
}
1153+
for _, tt := range tests {
1154+
t.Run(tt.name, func(t *testing.T) {
1155+
var dest int32
1156+
err := BindStyledParameterWithOptions("matrix", "param", tt.value, &dest, BindStyledParameterOptions{
1157+
ParamLocation: ParamLocationPath,
1158+
Explode: tt.explode,
1159+
Required: true,
1160+
})
1161+
require.NoError(t, err)
1162+
assert.Equal(t, tt.want, dest)
1163+
})
1164+
}
1165+
}
1166+
11191167
func TestBindStyledParameterWithLocation(t *testing.T) {
11201168
t.Run("bigNumber", func(t *testing.T) {
11211169
expectedBig := big.NewInt(12345678910)

0 commit comments

Comments
 (0)