// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>// SPDX-License-Identifier: MITpackage rtcpimport ()/*Converts an RTCP Packet into a human-readable format. The Packetsthemselves can control the presentation as follows: - Fields of a type that have a String() method will be formatted with that String method (which should not emit '\n' characters) - Otherwise, fields with a tag containing a "fmt" string will use that format when serializing the value. For example, to format an SSRC value as base 16 insted of base 10: type ExamplePacket struct { LocalSSRC uint32 `fmt:"0x%X"` RemotsSSRCs []uint32 `fmt:"%X"` }- If no fmt string is present, "%+v" is used by defaultThe intention of this stringify() function is to simplify creationof String() methods on new packet types, as it provides a simplebaseline implementation that works well in the majority of cases.*/func stringify( Packet) string { := reflect.Indirect(reflect.ValueOf())returnformatField(.Type().String(), "", , "")}func formatField( string, string, interface{}, string) string { //nolint:gocognit := := reflect.ValueOf()if !.IsValid() {returnfmt.Sprintf("%s%s: <nil>\n", , ) } := reflect.TypeOf().Implements(reflect.TypeOf((*Packet)(nil)).Elem())// Resolve pointers to their underlying valuesif .Type().Kind() == reflect.Ptr && !.IsNil() { := reflect.Indirect()if .IsValid() { = } }// If the field type has a custom String method, use that // (unless we're a packet, since we want to avoid recursing // back into this function if the Packet's String() method // uses it)if := .MethodByName("String"); ! && .IsValid() { += fmt.Sprintf("%s: %s\n", , .Call([]reflect.Value{}))return }switch .Kind() {casereflect.Struct: += fmt.Sprintf("%s:\n", )for := 0; < .NumField(); ++ {if .Field().CanInterface() { = .Type().Field().Tag.Get("fmt")if == "" { = "%+v" } += (.Type().Field().Name, , .Field().Interface(), +"\t") } }casereflect.Slice: := .Type().Elem().Kind() , := .Type().Elem().MethodByName("String")if || == reflect.Struct || == reflect.Ptr || == reflect.Interface || == reflect.Slice { += fmt.Sprintf("%s:\n", )for := 0; < .Len(); ++ { := fmt.Sprint()// Since interfaces can hold different types of things, we add the // most specific type name to the name to make it clear what the // subsequent fields represent.if .Index().Kind() == reflect.Interface { += fmt.Sprintf(" (%s)", reflect.Indirect(reflect.ValueOf(.Index().Interface())).Type()) }if .Index().CanInterface() { += (, , .Index().Interface(), +"\t") } }return }// If we didn't take care of stringing the value already, we fall through to the // generic case. This will print slices of basic types on a single line.fallthroughdefault:if .CanInterface() { += fmt.Sprintf("%s: "++"\n", , .Interface()) } }return}
The pages are generated with Goldsv0.8.2. (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu.
PR and bug reports are welcome and can be submitted to the issue list.
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds.