Skip to content

Commit 7ad6ecd

Browse files
mromaszewiczclaude
andcommitted
fix: strip style prefix for label/matrix primitive parameters (#99)
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 b76a24f commit 7ad6ecd

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
@@ -152,8 +152,16 @@ func BindStyledParameterWithOptions(style string, paramName string, value string
152152
return bindSplitPartsToDestinationArray(parts, dest)
153153
}
154154

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

159167
// 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
@@ -1101,6 +1101,54 @@ func TestRoundTripQueryParameter(t *testing.T) {
11011101
})
11021102
}
11031103

1104+
func TestBindStyledParameterWithOptions_LabelPrimitive(t *testing.T) {
1105+
tests := []struct {
1106+
name string
1107+
explode bool
1108+
value string
1109+
want int32
1110+
}{
1111+
{"non-exploded", false, ".5", 5},
1112+
{"exploded", true, ".5", 5},
1113+
}
1114+
for _, tt := range tests {
1115+
t.Run(tt.name, func(t *testing.T) {
1116+
var dest int32
1117+
err := BindStyledParameterWithOptions("label", "param", tt.value, &dest, BindStyledParameterOptions{
1118+
ParamLocation: ParamLocationPath,
1119+
Explode: tt.explode,
1120+
Required: true,
1121+
})
1122+
require.NoError(t, err)
1123+
assert.Equal(t, tt.want, dest)
1124+
})
1125+
}
1126+
}
1127+
1128+
func TestBindStyledParameterWithOptions_MatrixPrimitive(t *testing.T) {
1129+
tests := []struct {
1130+
name string
1131+
explode bool
1132+
value string
1133+
want int32
1134+
}{
1135+
{"non-exploded", false, ";param=5", 5},
1136+
{"exploded", true, ";param=5", 5},
1137+
}
1138+
for _, tt := range tests {
1139+
t.Run(tt.name, func(t *testing.T) {
1140+
var dest int32
1141+
err := BindStyledParameterWithOptions("matrix", "param", tt.value, &dest, BindStyledParameterOptions{
1142+
ParamLocation: ParamLocationPath,
1143+
Explode: tt.explode,
1144+
Required: true,
1145+
})
1146+
require.NoError(t, err)
1147+
assert.Equal(t, tt.want, dest)
1148+
})
1149+
}
1150+
}
1151+
11041152
func TestBindStyledParameterWithLocation(t *testing.T) {
11051153
t.Run("bigNumber", func(t *testing.T) {
11061154
expectedBig := big.NewInt(12345678910)

0 commit comments

Comments
 (0)