mirror of
https://github.com/ceph/ceph-csi.git
synced 2024-11-15 19:00:19 +00:00
217 lines
5.5 KiB
Go
217 lines
5.5 KiB
Go
|
// Copyright 2023 Google LLC
|
||
|
//
|
||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
// you may not use this file except in compliance with the License.
|
||
|
// You may obtain a copy of the License at
|
||
|
//
|
||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||
|
//
|
||
|
// Unless required by applicable law or agreed to in writing, software
|
||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
// See the License for the specific language governing permissions and
|
||
|
// limitations under the License.
|
||
|
|
||
|
package checker
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"strings"
|
||
|
|
||
|
chkdecls "github.com/google/cel-go/checker/decls"
|
||
|
"github.com/google/cel-go/common/types"
|
||
|
|
||
|
exprpb "google.golang.org/genproto/googleapis/api/expr/v1alpha1"
|
||
|
)
|
||
|
|
||
|
const (
|
||
|
kindUnknown = iota + 1
|
||
|
kindError
|
||
|
kindFunction
|
||
|
kindDyn
|
||
|
kindPrimitive
|
||
|
kindWellKnown
|
||
|
kindWrapper
|
||
|
kindNull
|
||
|
kindAbstract
|
||
|
kindType
|
||
|
kindList
|
||
|
kindMap
|
||
|
kindObject
|
||
|
kindTypeParam
|
||
|
)
|
||
|
|
||
|
// FormatCheckedType converts a type message into a string representation.
|
||
|
func FormatCheckedType(t *exprpb.Type) string {
|
||
|
switch kindOf(t) {
|
||
|
case kindDyn:
|
||
|
return "dyn"
|
||
|
case kindFunction:
|
||
|
return formatFunctionExprType(t.GetFunction().GetResultType(),
|
||
|
t.GetFunction().GetArgTypes(),
|
||
|
false)
|
||
|
case kindList:
|
||
|
return fmt.Sprintf("list(%s)", FormatCheckedType(t.GetListType().GetElemType()))
|
||
|
case kindObject:
|
||
|
return t.GetMessageType()
|
||
|
case kindMap:
|
||
|
return fmt.Sprintf("map(%s, %s)",
|
||
|
FormatCheckedType(t.GetMapType().GetKeyType()),
|
||
|
FormatCheckedType(t.GetMapType().GetValueType()))
|
||
|
case kindNull:
|
||
|
return "null"
|
||
|
case kindPrimitive:
|
||
|
switch t.GetPrimitive() {
|
||
|
case exprpb.Type_UINT64:
|
||
|
return "uint"
|
||
|
case exprpb.Type_INT64:
|
||
|
return "int"
|
||
|
}
|
||
|
return strings.Trim(strings.ToLower(t.GetPrimitive().String()), " ")
|
||
|
case kindType:
|
||
|
if t.GetType() == nil || t.GetType().GetTypeKind() == nil {
|
||
|
return "type"
|
||
|
}
|
||
|
return fmt.Sprintf("type(%s)", FormatCheckedType(t.GetType()))
|
||
|
case kindWellKnown:
|
||
|
switch t.GetWellKnown() {
|
||
|
case exprpb.Type_ANY:
|
||
|
return "any"
|
||
|
case exprpb.Type_DURATION:
|
||
|
return "duration"
|
||
|
case exprpb.Type_TIMESTAMP:
|
||
|
return "timestamp"
|
||
|
}
|
||
|
case kindWrapper:
|
||
|
return fmt.Sprintf("wrapper(%s)",
|
||
|
FormatCheckedType(chkdecls.NewPrimitiveType(t.GetWrapper())))
|
||
|
case kindError:
|
||
|
return "!error!"
|
||
|
case kindTypeParam:
|
||
|
return t.GetTypeParam()
|
||
|
case kindAbstract:
|
||
|
at := t.GetAbstractType()
|
||
|
params := at.GetParameterTypes()
|
||
|
paramStrs := make([]string, len(params))
|
||
|
for i, p := range params {
|
||
|
paramStrs[i] = FormatCheckedType(p)
|
||
|
}
|
||
|
return fmt.Sprintf("%s(%s)", at.GetName(), strings.Join(paramStrs, ", "))
|
||
|
}
|
||
|
return t.String()
|
||
|
}
|
||
|
|
||
|
type formatter func(any) string
|
||
|
|
||
|
// FormatCELType formats a types.Type value to a string representation.
|
||
|
//
|
||
|
// The type formatting is identical to FormatCheckedType.
|
||
|
func FormatCELType(t any) string {
|
||
|
dt := t.(*types.Type)
|
||
|
switch dt.Kind() {
|
||
|
case types.AnyKind:
|
||
|
return "any"
|
||
|
case types.DurationKind:
|
||
|
return "duration"
|
||
|
case types.ErrorKind:
|
||
|
return "!error!"
|
||
|
case types.NullTypeKind:
|
||
|
return "null"
|
||
|
case types.TimestampKind:
|
||
|
return "timestamp"
|
||
|
case types.TypeParamKind:
|
||
|
return dt.TypeName()
|
||
|
case types.OpaqueKind:
|
||
|
if dt.TypeName() == "function" {
|
||
|
// There is no explicit function type in the new types representation, so information like
|
||
|
// whether the function is a member function is absent.
|
||
|
return formatFunctionDeclType(dt.Parameters()[0], dt.Parameters()[1:], false)
|
||
|
}
|
||
|
case types.UnspecifiedKind:
|
||
|
return ""
|
||
|
}
|
||
|
if len(dt.Parameters()) == 0 {
|
||
|
return dt.DeclaredTypeName()
|
||
|
}
|
||
|
paramTypeNames := make([]string, 0, len(dt.Parameters()))
|
||
|
for _, p := range dt.Parameters() {
|
||
|
paramTypeNames = append(paramTypeNames, FormatCELType(p))
|
||
|
}
|
||
|
return fmt.Sprintf("%s(%s)", dt.TypeName(), strings.Join(paramTypeNames, ", "))
|
||
|
}
|
||
|
|
||
|
func formatExprType(t any) string {
|
||
|
if t == nil {
|
||
|
return ""
|
||
|
}
|
||
|
return FormatCheckedType(t.(*exprpb.Type))
|
||
|
}
|
||
|
|
||
|
func formatFunctionExprType(resultType *exprpb.Type, argTypes []*exprpb.Type, isInstance bool) string {
|
||
|
return formatFunctionInternal[*exprpb.Type](resultType, argTypes, isInstance, formatExprType)
|
||
|
}
|
||
|
|
||
|
func formatFunctionDeclType(resultType *types.Type, argTypes []*types.Type, isInstance bool) string {
|
||
|
return formatFunctionInternal[*types.Type](resultType, argTypes, isInstance, FormatCELType)
|
||
|
}
|
||
|
|
||
|
func formatFunctionInternal[T any](resultType T, argTypes []T, isInstance bool, format formatter) string {
|
||
|
result := ""
|
||
|
if isInstance {
|
||
|
target := argTypes[0]
|
||
|
argTypes = argTypes[1:]
|
||
|
result += format(target)
|
||
|
result += "."
|
||
|
}
|
||
|
result += "("
|
||
|
for i, arg := range argTypes {
|
||
|
if i > 0 {
|
||
|
result += ", "
|
||
|
}
|
||
|
result += format(arg)
|
||
|
}
|
||
|
result += ")"
|
||
|
rt := format(resultType)
|
||
|
if rt != "" {
|
||
|
result += " -> "
|
||
|
result += rt
|
||
|
}
|
||
|
return result
|
||
|
}
|
||
|
|
||
|
// kindOf returns the kind of the type as defined in the checked.proto.
|
||
|
func kindOf(t *exprpb.Type) int {
|
||
|
if t == nil || t.TypeKind == nil {
|
||
|
return kindUnknown
|
||
|
}
|
||
|
switch t.GetTypeKind().(type) {
|
||
|
case *exprpb.Type_Error:
|
||
|
return kindError
|
||
|
case *exprpb.Type_Function:
|
||
|
return kindFunction
|
||
|
case *exprpb.Type_Dyn:
|
||
|
return kindDyn
|
||
|
case *exprpb.Type_Primitive:
|
||
|
return kindPrimitive
|
||
|
case *exprpb.Type_WellKnown:
|
||
|
return kindWellKnown
|
||
|
case *exprpb.Type_Wrapper:
|
||
|
return kindWrapper
|
||
|
case *exprpb.Type_Null:
|
||
|
return kindNull
|
||
|
case *exprpb.Type_Type:
|
||
|
return kindType
|
||
|
case *exprpb.Type_ListType_:
|
||
|
return kindList
|
||
|
case *exprpb.Type_MapType_:
|
||
|
return kindMap
|
||
|
case *exprpb.Type_MessageType:
|
||
|
return kindObject
|
||
|
case *exprpb.Type_TypeParam:
|
||
|
return kindTypeParam
|
||
|
case *exprpb.Type_AbstractType_:
|
||
|
return kindAbstract
|
||
|
}
|
||
|
return kindUnknown
|
||
|
}
|