validation-gen/util: add ParseInt utility for canonical integer parsing

Signed-off-by: Bryce Palmer <bpalmer@redhat.com>
This commit is contained in:
Bryce Palmer
2026-02-27 09:49:46 -05:00
parent b5dd643c95
commit fff6e5950d
2 changed files with 75 additions and 0 deletions

View File

@@ -17,6 +17,9 @@ limitations under the License.
package util
import (
"fmt"
"strconv"
"k8s.io/gengo/v2/parser/tags"
"k8s.io/gengo/v2/types"
)
@@ -114,3 +117,23 @@ func IsDirectComparable(t *types.Type) bool {
}
return false
}
// ParseInt strictly parses an int from a string input,
// ensuring that when converted back to a string, the resulting
// int and the input string have the exact same representation.
// This prevents scenarios where an input like `0100` parses
// as 100 and would be re-stringed as `100`.
func ParseInt(val string) (int, error) {
intVal, err := strconv.Atoi(val)
if err != nil {
return 0, fmt.Errorf("parsing %q as int: %w", val, err)
}
strVal := strconv.Itoa(intVal)
if strVal != val {
err := fmt.Errorf("parsed int %d converted to a string value of %q which does not match the input string", intVal, strVal)
return 0, fmt.Errorf("parsing %q as int: %w", val, err)
}
return intVal, nil
}

View File

@@ -452,3 +452,55 @@ func TestIsDirectComparable(t *testing.T) {
}
}
}
func TestParseInt(t *testing.T) {
type testcase struct {
name string
in string
expectedOut int
expectedError bool
}
testcases := []testcase{
{
name: "valid canonical integer string",
in: "100",
expectedOut: 100,
expectedError: false,
},
{
name: "invalid canonical integer string, not an integer at all",
in: "notanint",
expectedOut: 0,
expectedError: true,
},
{
name: "invalid canonical integer string, spurious leading zeros",
in: "00100",
expectedOut: 0,
expectedError: true,
},
{
name: "invalid canonical integer string, octal value",
in: "0o123",
expectedOut: 0,
expectedError: true,
},
}
for _, tc := range testcases {
t.Run(tc.name, func(t *testing.T) {
out, err := ParseInt(tc.in)
switch {
case tc.expectedError && err == nil:
t.Error("expected an error but did not receive one")
case !tc.expectedError && err != nil:
t.Errorf("received an unexpected error: %v", err)
}
if out != tc.expectedOut {
t.Errorf("expected an output value of %d but got %d", tc.expectedOut, out)
}
})
}
}