Rumah >pembangunan bahagian belakang >Golang >Bagaimanakah Saya Boleh Menghuraikan Mesej Protobuf Tidak Diketahui Tanpa Maklumat Jenis?

Bagaimanakah Saya Boleh Menghuraikan Mesej Protobuf Tidak Diketahui Tanpa Maklumat Jenis?

Patricia Arquette
Patricia Arquetteasal
2024-11-28 01:36:10715semak imbas

How Can I Parse Unknown Protobuf Messages Without Type Information?

Unknown Message Proto Demarshalling Without Type Information

Walaupun kaedah proto.Unmarshal() protobuf memerlukan jenis mesej yang diketahui, mesej yang tidak diketahui memberikan cabaran . Walau bagaimanapun, kami boleh mengekstrak maklumat terhad menggunakan pakej protowire.

Pendekatan:

  1. Gunakan protowire.ConsumeField() untuk beralih melalui muatan mesej yang tidak diketahui.
  2. Kenal pasti jenis medan, yang boleh menjadi:

    • Varin
    • Fixed64
    • Bytes
    • StartGroup
    • Fixed32
  3. Menghuraikan muatan medan berdasarkannya taip.
  4. Kendalikan submesej dengan menghuraikan muatannya secara rekursif.

Model Data:

type Field struct {
    Tag Tag
    Val Val
}

type Tag struct {
    Num int32
    Type protowire.Type
}

type Val struct {
    Payload interface{}
    Length int
}

Penghurai:

func parseUnknown(b []byte) []Field {
    // Iteratively consume and parse fields
    for len(b) > 0 {
        // Read field tag and length
        n, t, fieldlen := protowire.ConsumeField(b)
        if fieldlen < 1 {
            return nil
        }
        field := Field{Tag: Tag{Num: int32(n), Type: t}}

        // Read and process tag and value content
        _, _, taglen := protowire.ConsumeTag(b[:fieldlen])
        if taglen < 1 {
            return nil
        }
        var v interface{}
        var vlen int
        switch t {
            case protowire.VarintType:
                v, vlen = protowire.ConsumeVarint(b[taglen:fieldlen])
            case protowire.Fixed64Type:
                v, vlen = protowire.ConsumeFixed64(b[taglen:fieldlen])
            case protowire.BytesType:
                v, vlen = protowire.ConsumeBytes(b[taglen:fieldlen])
                sub := parseUnknown(v.([]byte))
                if sub != nil {
                    v = sub
                }
            case protowire.StartGroupType:
                v, vlen = protowire.ConsumeGroup(n, b[taglen:fieldlen])
                sub := parseUnknown(v.([]byte))
                if sub != nil {
                    v = sub
                }
            case protowire.Fixed32Type:
                v, vlen = protowire.ConsumeFixed32(b[taglen:fieldlen])
        }
        if vlen < 1 {
            return nil
        }

        field.Val = Val{Payload: v, Length: vlen - taglen}
        fields = append(fields, field)
        b = b[fieldlen:]
    }
    return fields
}

Contoh (Struktur Mesej):

message Foo {
  string a = 1;
  string b = 2;
  Bar bar = 3;
}

message Bar {
  string c = 1;
}

Contoh (Output Dihurai):

main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x41}, Length:1}}
main.Field{Tag:main.Tag{Num:2, Type:2}, Val:main.Val{Payload:[]uint8{0x42}, Length:1}}
main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}
main.Field{Tag:main.Tag{Num:3, Type:2}, Val:main.Val{Payload:[]main.Field{main.Field{Tag:main.Tag{Num:1, Type:2}, Val:main.Val{Payload:[]uint8{0x43}, Length:1}}}, Length:3}}

Pertimbangan:

  • Sub-mesej: Penghuraian rekursif daripada muatan bait yang dikenal pasti sebagai mesej.
  • Medan berulang: Dikendalikan berdasarkan nombor teg medan yang sama.
  • Peta: Diandaikan serupa dengan berulang pasangan k/v.
  • Salah satu: Kesatuan maklumat jenis hilang, hanya nilai sebenar dihuraikan.
Walaupun kod ini tidak menyediakan penyelesaian gred pengeluaran yang lengkap, ia menawarkan kaedah untuk menghuraikan muatan proto yang tidak diketahui sambil mengekalkan beberapa maklumat semantik.

Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Menghuraikan Mesej Protobuf Tidak Diketahui Tanpa Maklumat Jenis?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn