Maison >développement back-end >Golang >Comment désorganiser les messages Protobuf inconnus dans Go ?

Comment désorganiser les messages Protobuf inconnus dans Go ?

Linda Hamilton
Linda Hamiltonoriginal
2024-12-03 02:15:10733parcourir

How to Unmarshal Unknown Protobuf Messages in Go?

Désassembler les messages Protobuf inconnus dans Go

Désassembler les messages protobuf dans une interface{} pour faciliter la conversion de type n'est pas réalisable car la fonction proto.Unmarshal attend un argument de type proto.Message, une interface implémentée par des types protobuf concrets.

Approche alternative avec métadonnées connues

Dans les cas où au moins certaines informations contextuelles (par exemple, une chaîne ou un nombre) accompagnent la tranche d'octets, vous pouvez utiliser ces informations pour mapper le type de protobuf attendu et l'instancier avant de le transmettre à proto .Unmarshal :

func decodeWithMetadata(data []byte, identifier string) error {
    var message proto.Message
    switch identifier {
        case "foo":
            message = &mypb.Foo{}
        case "bar":
            message = &mypb.Bar{}
    }
    if err := proto.Unmarshal(data, message); err != nil {
        return err
    }
    log.Printf("%v\n", data)
    return nil
}

Analyse de charges utiles complètement inconnues

Cependant, si la charge utile de l'octet est entièrement inconnue, considérez le package protowire, qui permet d'extraire des informations limitées à partir de messages protobuf au format filaire. Gardez à l'esprit que la représentation filaire des messages protobuf est ambiguë, ce qui conduit à une sémantique faible.

Implémentation de l'analyseur

Le code suivant analyse les messages protobuf inconnus :

type Field struct {
    Tag Tag
    Val Val
}

type Tag struct {
    Num int32
    Type protowire.Type
}

type Val struct {
    Payload interface{}
    Length int
}

func parseUnknown(b []byte) []Field {
    // ... implementation to parse unknown protobuf messages as described in the provided answer ...
}

Exemple Utilisation

Étant donné un schéma protobuf comme :

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

message Bar {
  string c = 1;
}

Le code suivant montre comment utiliser l'analyseur :

// Parse the protobuf message as byte slice
b := []byte{0x0a, 0x01, 0x41, 0x12, 0x01, 0x42, 0x1a, 0x03, 0x43}
fields := parseUnknown(b)
for _, field := range fields {
    fmt.Printf("%#v\n", field)
}

Sortie :

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}}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn