2026-03-19 14:52:12 +03:00
|
|
|
package parser
|
|
|
|
|
|
|
|
|
|
type PrimitiveKind int
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
KindFloat32 PrimitiveKind = iota
|
|
|
|
|
KindFloat64
|
|
|
|
|
KindInt8
|
|
|
|
|
KindInt16
|
|
|
|
|
KindInt32
|
|
|
|
|
KindInt64
|
|
|
|
|
KindUint8
|
|
|
|
|
KindUint16
|
|
|
|
|
KindUint32
|
|
|
|
|
KindUint64
|
|
|
|
|
KindBool
|
|
|
|
|
KindString
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type FieldKind int
|
|
|
|
|
|
|
|
|
|
const (
|
2026-03-23 09:47:14 +03:00
|
|
|
KindPrimitive FieldKind = iota
|
|
|
|
|
KindNested
|
|
|
|
|
KindFixedArray
|
|
|
|
|
KindSlice
|
2026-03-19 14:52:12 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type QuantInfo struct {
|
|
|
|
|
Min float64
|
|
|
|
|
Max float64
|
2026-03-23 09:47:14 +03:00
|
|
|
Bits int // 8 or 16, default 16
|
2026-03-19 14:52:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *QuantInfo) MaxUint() float64 {
|
|
|
|
|
if q.Bits == 8 {
|
|
|
|
|
return 255
|
|
|
|
|
}
|
|
|
|
|
return 65535
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (q *QuantInfo) WireBytes() int {
|
|
|
|
|
return q.Bits / 8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Field struct {
|
|
|
|
|
Name string
|
|
|
|
|
Kind FieldKind
|
|
|
|
|
|
|
|
|
|
Primitive PrimitiveKind
|
|
|
|
|
NamedType string
|
2026-03-23 09:47:14 +03:00
|
|
|
Quant *QuantInfo
|
2026-03-19 14:52:12 +03:00
|
|
|
|
|
|
|
|
TypeName string
|
|
|
|
|
|
|
|
|
|
Elem *Field
|
2026-03-23 09:47:14 +03:00
|
|
|
FixedLen int
|
2026-03-19 14:52:12 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Field) WireSize() int {
|
|
|
|
|
switch f.Kind {
|
|
|
|
|
case KindPrimitive:
|
|
|
|
|
if f.Quant != nil {
|
|
|
|
|
return f.Quant.WireBytes()
|
|
|
|
|
}
|
|
|
|
|
return primitiveWireSize(f.Primitive)
|
|
|
|
|
case KindNested:
|
2026-03-23 09:47:14 +03:00
|
|
|
return -1
|
2026-03-19 14:52:12 +03:00
|
|
|
case KindFixedArray:
|
|
|
|
|
elemSize := f.Elem.WireSize()
|
|
|
|
|
if elemSize == -1 {
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
return f.FixedLen * elemSize
|
|
|
|
|
case KindSlice:
|
2026-03-23 09:47:14 +03:00
|
|
|
return -1
|
2026-03-19 14:52:12 +03:00
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func primitiveWireSize(k PrimitiveKind) int {
|
|
|
|
|
switch k {
|
|
|
|
|
case KindFloat32, KindInt32, KindUint32:
|
|
|
|
|
return 4
|
|
|
|
|
case KindFloat64, KindInt64, KindUint64:
|
|
|
|
|
return 8
|
|
|
|
|
case KindInt16, KindUint16:
|
|
|
|
|
return 2
|
|
|
|
|
case KindInt8, KindUint8, KindBool:
|
|
|
|
|
return 1
|
|
|
|
|
case KindString:
|
|
|
|
|
return -1
|
|
|
|
|
}
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func IsIntegralPrimitive(k PrimitiveKind) bool {
|
|
|
|
|
switch k {
|
|
|
|
|
case KindInt8, KindInt16, KindInt32, KindInt64, KindUint8, KindUint16, KindUint32, KindUint64:
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Field) GoTypeName() string {
|
|
|
|
|
switch f.Kind {
|
|
|
|
|
case KindPrimitive:
|
|
|
|
|
if f.NamedType != "" {
|
|
|
|
|
return f.NamedType
|
|
|
|
|
}
|
|
|
|
|
return primitiveGoName(f.Primitive)
|
|
|
|
|
case KindNested:
|
|
|
|
|
return f.TypeName
|
|
|
|
|
case KindFixedArray:
|
|
|
|
|
return "[" + itoa(f.FixedLen) + "]" + f.Elem.GoTypeName()
|
|
|
|
|
case KindSlice:
|
|
|
|
|
return "[]" + f.Elem.GoTypeName()
|
|
|
|
|
}
|
|
|
|
|
return "unknown"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Field) CSharpTypeName() string {
|
|
|
|
|
switch f.Kind {
|
|
|
|
|
case KindPrimitive:
|
|
|
|
|
if f.NamedType != "" {
|
|
|
|
|
return f.NamedType
|
|
|
|
|
}
|
|
|
|
|
return primitiveCSharpName(f.Primitive)
|
|
|
|
|
case KindNested:
|
|
|
|
|
return f.TypeName
|
|
|
|
|
case KindFixedArray:
|
|
|
|
|
return f.Elem.CSharpTypeName() + "[]"
|
|
|
|
|
case KindSlice:
|
|
|
|
|
return f.Elem.CSharpTypeName() + "[]"
|
|
|
|
|
}
|
|
|
|
|
return "unknown"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func primitiveGoName(k PrimitiveKind) string {
|
|
|
|
|
switch k {
|
|
|
|
|
case KindFloat32:
|
|
|
|
|
return "float32"
|
|
|
|
|
case KindFloat64:
|
|
|
|
|
return "float64"
|
|
|
|
|
case KindInt8:
|
|
|
|
|
return "int8"
|
|
|
|
|
case KindInt16:
|
|
|
|
|
return "int16"
|
|
|
|
|
case KindInt32:
|
|
|
|
|
return "int32"
|
|
|
|
|
case KindInt64:
|
|
|
|
|
return "int64"
|
|
|
|
|
case KindUint8:
|
|
|
|
|
return "uint8"
|
|
|
|
|
case KindUint16:
|
|
|
|
|
return "uint16"
|
|
|
|
|
case KindUint32:
|
|
|
|
|
return "uint32"
|
|
|
|
|
case KindUint64:
|
|
|
|
|
return "uint64"
|
|
|
|
|
case KindBool:
|
|
|
|
|
return "bool"
|
|
|
|
|
case KindString:
|
|
|
|
|
return "string"
|
|
|
|
|
}
|
|
|
|
|
return "unknown"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Field) GoPrimitiveTypeName() string {
|
|
|
|
|
return primitiveGoName(f.Primitive)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func primitiveCSharpName(k PrimitiveKind) string {
|
|
|
|
|
switch k {
|
|
|
|
|
case KindFloat32:
|
|
|
|
|
return "float"
|
|
|
|
|
case KindFloat64:
|
|
|
|
|
return "double"
|
|
|
|
|
case KindInt8:
|
|
|
|
|
return "sbyte"
|
|
|
|
|
case KindInt16:
|
|
|
|
|
return "short"
|
|
|
|
|
case KindInt32:
|
|
|
|
|
return "int"
|
|
|
|
|
case KindInt64:
|
|
|
|
|
return "long"
|
|
|
|
|
case KindUint8:
|
|
|
|
|
return "byte"
|
|
|
|
|
case KindUint16:
|
|
|
|
|
return "ushort"
|
|
|
|
|
case KindUint32:
|
|
|
|
|
return "uint"
|
|
|
|
|
case KindUint64:
|
|
|
|
|
return "ulong"
|
|
|
|
|
case KindBool:
|
|
|
|
|
return "bool"
|
|
|
|
|
case KindString:
|
|
|
|
|
return "string"
|
|
|
|
|
}
|
|
|
|
|
return "unknown"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (f *Field) CSharpPrimitiveTypeName() string {
|
|
|
|
|
return primitiveCSharpName(f.Primitive)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func itoa(n int) string {
|
|
|
|
|
if n == 0 {
|
|
|
|
|
return "0"
|
|
|
|
|
}
|
|
|
|
|
buf := [20]byte{}
|
|
|
|
|
pos := len(buf)
|
|
|
|
|
for n > 0 {
|
|
|
|
|
pos--
|
|
|
|
|
buf[pos] = byte('0' + n%10)
|
|
|
|
|
n /= 10
|
|
|
|
|
}
|
|
|
|
|
return string(buf[pos:])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Message struct {
|
|
|
|
|
PackageName string
|
|
|
|
|
Name string
|
|
|
|
|
Fields []Field
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type EnumValue struct {
|
|
|
|
|
Name string
|
|
|
|
|
Value string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Enum struct {
|
|
|
|
|
Name string
|
|
|
|
|
Primitive PrimitiveKind
|
|
|
|
|
Values []EnumValue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type Schema struct {
|
|
|
|
|
PackageName string
|
|
|
|
|
Messages []Message
|
|
|
|
|
Enums []Enum
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *Message) MinWireSize() int {
|
|
|
|
|
total := 0
|
|
|
|
|
for _, f := range m.Fields {
|
|
|
|
|
s := f.WireSize()
|
|
|
|
|
if s == -1 {
|
2026-03-23 09:47:14 +03:00
|
|
|
total += 2
|
2026-03-19 14:52:12 +03:00
|
|
|
} else {
|
|
|
|
|
total += s
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return total
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (m *Message) HasVariableFields() bool {
|
|
|
|
|
for _, f := range m.Fields {
|
|
|
|
|
if f.WireSize() == -1 {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|