Skip to content

Commit

Permalink
Enhance simpleschema package to support nested complex types (#31)
Browse files Browse the repository at this point in the history
This commit significantly improves the `simpleschema` package ability to handle
complex, nested data structures. The `parseMapType` function has been refactored
to correctly parse nested map types and a new `findMatchingBracket` function has
been added to ensure robust bracket parsing. The Transformer.BuildOpenAPISchema
method has been restructured allowing for more flexible and accurate schema
generation for nested slices and maps.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
  • Loading branch information
a-hilaly authored Sep 27, 2024
1 parent 343a43e commit efc8260
Showing 5 changed files with 294 additions and 153 deletions.
45 changes: 39 additions & 6 deletions internal/typesystem/simpleschema/atomic.go
Original file line number Diff line number Diff line change
@@ -80,21 +80,54 @@ func isSliceType(s string) bool {

// parseMapType parses a map type string and returns the key and value types.
func parseMapType(s string) (string, string, error) {
// Remove the "map[" prefix and "]" suffix.
s = strings.TrimPrefix(s, "map[")
s = strings.TrimSuffix(s, "]")
parts := strings.Split(s, "]")
if len(parts) != 2 {
if !strings.HasPrefix(s, "map[") {
return "", "", fmt.Errorf("invalid map type: %s", s)
}
return parts[0], parts[1], nil

// remove the "map[" prefix
s = s[4:]

keyEndIndex := findMatchingBracket(s)
if keyEndIndex == -1 {
return "", "", fmt.Errorf("invalid map key type: %s", s)
}

keyType := s[:keyEndIndex]
valueType := s[keyEndIndex+1:]

valueType = strings.TrimSuffix(valueType, "]")
if keyType == "" {
return "", "", fmt.Errorf("empty map key type")
}
if valueType == "" {
return "", "", fmt.Errorf("empty map value type")
}

return keyType, valueType, nil
}
func findMatchingBracket(s string) int {
depth := 1
for i, char := range s {
switch char {
case '[':
depth++
case ']':
depth--
if depth == 0 {
return i
}
}
}
// no matching bracket found
return -1
}

// parseSliceType parses a slice type string and returns the element type.
func parseSliceType(s string) (string, error) {
if !strings.HasPrefix(s, "[]") {
return "", fmt.Errorf("invalid slice type: %s", s)
}

// Remove the "[]" prefix.
s = strings.TrimPrefix(s, "[]")
if s == "" {
9 changes: 5 additions & 4 deletions internal/typesystem/simpleschema/atomic_test.go
Original file line number Diff line number Diff line change
@@ -112,8 +112,9 @@ func TestParseMapType(t *testing.T) {
wantErr bool
}{
{"valid map", "map[string]integer", "string", "integer", false},
// not supported yet... do we need to support this?
// {"Valid Complex Map", "map[string]map[int]bool", "string", "map[int]bool", false},
{"Valid Complex Map", "map[string]map[int]bool", "string", "map[int]bool", false},
{"Nested Map", "map[string]map[string]map[string]integer", "string", "map[string]map[string]integer", false},
{"invalid map", "map[]", "", "", true},
{"invalid map", "map[string]", "", "", true},
{"not a map", "something", "", "", true},
}
@@ -143,8 +144,8 @@ func TestParseSliceType(t *testing.T) {
wantErr bool
}{
{"valid slice", "[]string", "string", false},
// not supported yet
// {"Valid Complex Slice", "[]map[string]int", "map[string]int", false},
{"Valid Complex Slice", "[]map[string]int", "map[string]int", false},
{"Nested Slice", "[][][]int", "[][]int", false},
{"invalid slice", "[]", "", true},
{"Not a slice", "string", "", true},
}
3 changes: 2 additions & 1 deletion internal/typesystem/simpleschema/field_test.go
Original file line number Diff line number Diff line change
@@ -32,7 +32,8 @@ func TestParseFieldSchema(t *testing.T) {
wantType: "string",
wantMarkers: []*Marker{
{MarkerType: MarkerTypeRequired, Key: "required", Value: "true"},
{MarkerType: MarkerTypeDescription, Key: "description", Value: "A test field"},
{MarkerType: MarkerTypeDescription, Key: "description", Value: "A-test-field"},
{MarkerType: MarkerTypeDefault, Key: "default", Value: "kubernetes-is-very-nice!"},
},
wantErr: false,
},
Loading

0 comments on commit efc8260

Please sign in to comment.