This commit is contained in:
2026-04-01 10:53:51 +03:00
parent 281af49d27
commit c1890216c5
16 changed files with 722 additions and 62 deletions
+33 -2
View File
@@ -14,6 +14,8 @@ func GenerateCSharp(messages []parser.Message, namespace string) ([]byte, error)
func GenerateCSharpSchema(schema parser.Schema, namespace string) ([]byte, error) {
messages := schema.Messages
var b strings.Builder
needsLengthGuards := schemaNeedsLengthGuards(messages)
needsQuantGuards := schemaNeedsQuantRangeGuards(messages)
b.WriteString("// <auto-generated> arpack </auto-generated>\n")
b.WriteString("// Code generated by arpack. DO NOT EDIT.\n")
@@ -27,6 +29,30 @@ func GenerateCSharpSchema(schema parser.Schema, namespace string) ([]byte, error
fmt.Fprintf(&b, "namespace %s\n{\n", namespace)
if needsLengthGuards || needsQuantGuards {
b.WriteString(" internal static class ArpackGenerated\n {\n")
if needsLengthGuards {
b.WriteString(" internal static ushort EnsureU16Length(int length, string context)\n")
b.WriteString(" {\n")
b.WriteString(" if (length > 65535)\n")
b.WriteString(" {\n")
b.WriteString(" throw new InvalidOperationException(\"arpack: \" + context + \" exceeds uint16 limit\");\n")
b.WriteString(" }\n")
b.WriteString(" return (ushort)length;\n")
b.WriteString(" }\n\n")
}
if needsQuantGuards {
b.WriteString(" internal static void EnsureQuantizedRange(double value, double min, double max, string context)\n")
b.WriteString(" {\n")
b.WriteString(" if (double.IsNaN(value) || value < min || value > max)\n")
b.WriteString(" {\n")
b.WriteString(" throw new ArgumentOutOfRangeException(context, \"arpack: quantized value out of range for \" + context);\n")
b.WriteString(" }\n")
b.WriteString(" }\n")
}
b.WriteString(" }\n\n")
}
enumNames := make(map[string]struct{}, len(schema.Enums))
for _, enum := range schema.Enums {
enumNames[enum.Name] = struct{}{}
@@ -151,7 +177,9 @@ func writeCSharpSerializeField(b *strings.Builder, f parser.Field, indent string
}
fmt.Fprintf(b, "%s}\n", indent)
case parser.KindSlice:
fmt.Fprintf(b, "%s*(ushort*)ptr = (ushort)(%s?.Length ?? 0); ptr += 2;\n", indent, f.Name)
lenVar := "_len" + sanitizeVarName(f.Name)
fmt.Fprintf(b, "%sushort %s = ArpackGenerated.EnsureU16Length(%s?.Length ?? 0, %q); *(ushort*)ptr = %s; ptr += 2;\n",
indent, lenVar, f.Name, lengthContext(f), lenVar)
fmt.Fprintf(b, "%sif (%s != null)\n%s{\n", indent, f.Name, indent)
iVar := "_i" + f.Name
fmt.Fprintf(b, "%s for (int %s = 0; %s < %s.Length; %s++)\n%s {\n",
@@ -212,7 +240,8 @@ func writeCSharpSerializePrimitive(
lenVar := "_slen" + sanitizeVarName(access)
fmt.Fprintf(b, "%sint %s = %s != null ? Encoding.UTF8.GetByteCount(%s) : 0;\n",
indent, lenVar, valueExpr, valueExpr)
fmt.Fprintf(b, "%s*(ushort*)ptr = (ushort)%s; ptr += 2;\n", indent, lenVar)
fmt.Fprintf(b, "%s*(ushort*)ptr = ArpackGenerated.EnsureU16Length(%s, %q); ptr += 2;\n",
indent, lenVar, lengthContext(f))
fmt.Fprintf(b, "%sif (%s != null && %s > 0)\n%s{\n", indent, valueExpr, lenVar, indent)
fmt.Fprintf(b, "%s fixed (char* _chars%s = %s)\n%s {\n",
indent, sanitizeVarName(access), valueExpr, indent)
@@ -228,6 +257,8 @@ func writeCSharpSerializePrimitive(
func writeCSharpSerializeQuant(b *strings.Builder, access string, f parser.Field, indent string) error {
q := f.Quant
maxUint := q.MaxUint()
fmt.Fprintf(b, "%sArpackGenerated.EnsureQuantizedRange(%s, %g, %g, %q);\n",
indent, access, q.Min, q.Max, quantContext(f))
if q.Bits == 8 {
fmt.Fprintf(b, "%s*ptr = (byte)((%s - (%gf)) / (%gf - (%gf)) * %gf); ptr += 1;\n",
indent, access, q.Min, q.Max, q.Min, maxUint)