diff --git a/tlv/go.mod b/tlv/go.mod index 341a042d1..51ee83e25 100644 --- a/tlv/go.mod +++ b/tlv/go.mod @@ -5,7 +5,9 @@ require ( github.com/btcsuite/btcd/btcec/v2 v2.1.3 github.com/davecgh/go-spew v1.1.1 github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 + github.com/lightningnetwork/lnd/fn v1.0.0 github.com/stretchr/testify v1.8.2 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d ) require ( @@ -14,7 +16,7 @@ require ( github.com/pmezard/go-difflib v1.0.0 // indirect github.com/rogpeppe/go-internal v1.9.0 // indirect golang.org/x/crypto v0.7.0 // indirect - golang.org/x/sys v0.8.0 // indirect + golang.org/x/sys v0.13.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/tlv/go.sum b/tlv/go.sum index 53e545b07..60d32c136 100644 --- a/tlv/go.sum +++ b/tlv/go.sum @@ -19,6 +19,8 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lightningnetwork/lnd/fn v1.0.0 h1:I5VG9AD63mOQ89RMQEu7HRI1r68wn8yz539LoylUIKM= +github.com/lightningnetwork/lnd/fn v1.0.0/go.mod h1:XV+0vBXSnh3aUjskJUv58TOpsveiXQ+ac8rEnXZDGFc= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= @@ -33,8 +35,10 @@ github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/tlv/internal/gen/gen_tlv_types.go b/tlv/internal/gen/gen_tlv_types.go new file mode 100644 index 000000000..d35a2b650 --- /dev/null +++ b/tlv/internal/gen/gen_tlv_types.go @@ -0,0 +1,59 @@ +package main + +import ( + "bytes" + "flag" + "os" + "text/template" +) + +const ( + numberOfTypes = 100 + defaultOutputFile = "tlv_types_generated.go" +) + +const typeCodeTemplate = `// Code generated by tlv/internal/gen; DO NOT EDIT. + +package tlv + +{{- range $index, $element := . }} + +type tlvType{{ $index }} struct{} + +func (t *tlvType{{ $index }}) typeVal() Type { + return {{ $index }} +} + +type TlvType{{ $index }} = *tlvType{{ $index }} +{{- end }} +` + +func main() { + // Create a slice of items that the template can range over. + var items []struct{} + for i := uint16(0); i <= numberOfTypes; i++ { + items = append(items, struct{}{}) + } + + tpl, err := template.New("tlv").Parse(typeCodeTemplate) + if err != nil { + panic(err) + } + + // Execute the template + var out bytes.Buffer + err = tpl.Execute(&out, items) + if err != nil { + panic(err) + } + + outputFile := flag.String( + "o", defaultOutputFile, "Output file for generated code", + ) + flag.Parse() + + err = os.WriteFile(*outputFile, out.Bytes(), 0644) + if err != nil { + panic(err) + } +} diff --git a/tlv/record_type.go b/tlv/record_type.go new file mode 100644 index 000000000..1b25a6ade --- /dev/null +++ b/tlv/record_type.go @@ -0,0 +1,85 @@ +package tlv + +import ( + "github.com/btcsuite/btcd/btcec/v2" + "github.com/lightningnetwork/lnd/fn" + "golang.org/x/exp/constraints" +) + +// RecordT is a high-order type makes it easy to encode known "primitive" types +// as TLV records. +type RecordT[T TlvType, V any] struct { + // recordType is the type of the TLV record. + recordType T + + // val is the value of the underlying record. Go doesn't let us just + // embed the type param as a struct field, so we need an intermediate + // variable. + Val V +} + +// RecordProducerT is a type-aware wrapper around the normal RecordProducer +// interface. +type RecordProducerT[T any] interface { + RecordProducer + + // This is a non-interface type constraint that allows us to pass a + // concrete type as a type parameter rather than a pointer to the type + // that satisfies the Record interface. + *T +} + +// NewRecordT creates a new RecordT type from a given RecordProducer type. This +// is useful to wrap a given record in this utility type, which also serves as +// an extra type annotation. The underlying type of the record is retained. +func NewRecordT[T TlvType, K any, V RecordProducerT[K]]( + record K, +) RecordT[T, K] { + + return RecordT[T, K]{ + Val: record, + } +} + +// Primitive is a type constraint that capture the set of "primitive" types, +// which are the built in stdlib types, and type defs of those types +type Primitive interface { + constraints.Unsigned | ~[]byte | ~[32]byte | ~[33]byte | ~bool | + ~*btcec.PublicKey | ~[64]byte +} + +// NewPrimitiveRecord creates a new RecordT type from a given primitive type. +func NewPrimitiveRecord[T TlvType, V Primitive](val V) RecordT[T, V] { + return RecordT[T, V]{ + Val: val, + } +} + +// Record returns the underlying record interface for the record type. +func (t *RecordT[T, V]) Record() Record { + // Go doesn't allow type assertions on a type param, so to work around + // this, we'll convert to any, then do our type assertion. + tlvRecord, ok := any(&t.Val).(RecordProducer) + if !ok { + return MakePrimitiveRecord( + t.recordType.typeVal(), &t.Val, + ) + } + + return tlvRecord.Record() +} + +// OptionalRecordT is a high-order type that represents an optional TLV record. +// This can be used when a TLV record doesn't always need to be present (ok to +// be odd). +type OptionalRecordT[T TlvType, V any] struct { + fn.Option[RecordT[T, V]] +} + +// ZeroRecordT returns a zero value of the RecordT type. +func ZeroRecordT[T TlvType, V any]() RecordT[T, V] { + var v V + return RecordT[T, V]{ + Val: v, + } +} diff --git a/tlv/record_type_test.go b/tlv/record_type_test.go new file mode 100644 index 000000000..29d2fc7b6 --- /dev/null +++ b/tlv/record_type_test.go @@ -0,0 +1,93 @@ +package tlv + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" +) + +const ( + fakeCsvDelayType = 1 + + fakeIsCoolType = 2 +) + +type fakeWireMsg struct { + CsvDelay RecordT[TlvType1, uint16] + + IsCool RecordT[TlvType2, bool] +} + +// TestRecordTFromPrimitive tests the RecordT type. We should be able to create +// types of both record types, and also primitive types, and encode/decode them +// as normal. +func TestRecordTFromPrimitive(t *testing.T) { + t.Parallel() + + wireMsg := fakeWireMsg{ + CsvDelay: NewPrimitiveRecord[TlvType1](uint16(5)), + IsCool: NewPrimitiveRecord[TlvType2](true), + } + + encodeStream, err := NewStream( + wireMsg.CsvDelay.Record(), wireMsg.IsCool.Record(), + ) + require.NoError(t, err) + + var b bytes.Buffer + err = encodeStream.Encode(&b) + require.NoError(t, err) + + var newWireMsg fakeWireMsg + + decodeStream, err := NewStream( + newWireMsg.CsvDelay.Record(), + newWireMsg.IsCool.Record(), + ) + require.NoError(t, err) + + err = decodeStream.Decode(&b) + require.NoError(t, err) + + require.Equal(t, wireMsg, newWireMsg) +} + +type wireCsv uint16 + +func (w *wireCsv) Record() Record { + return MakeStaticRecord(fakeCsvDelayType, (*uint16)(w), 2, EUint16, DUint16) +} + +type coolWireMsg struct { + CsvDelay RecordT[TlvType1, wireCsv] +} + +// TestRecordTFromRecord tests that we can create a RecordT type from an +// existing record type and encode/decode as normal. +func TestRecordTFromRecord(t *testing.T) { + t.Parallel() + + val := wireCsv(5) + + wireMsg := coolWireMsg{ + CsvDelay: NewRecordT[TlvType1](val), + } + + encodeStream, err := NewStream(wireMsg.CsvDelay.Record()) + require.NoError(t, err) + + var b bytes.Buffer + err = encodeStream.Encode(&b) + require.NoError(t, err) + + var wireMsg2 coolWireMsg + + decodeStream, err := NewStream(wireMsg2.CsvDelay.Record()) + require.NoError(t, err) + + err = decodeStream.Decode(&b) + require.NoError(t, err) + + require.Equal(t, wireMsg, wireMsg2) +} diff --git a/tlv/tlv_type_param.go b/tlv/tlv_type_param.go new file mode 100644 index 000000000..0d2c819f1 --- /dev/null +++ b/tlv/tlv_type_param.go @@ -0,0 +1,16 @@ +package tlv + +import "fmt" + +// TlvType is an interface used to enable binding the integer type of a TLV +// record to the type at compile time. +type TlvType interface { + typeVal() Type +} + +//go:generate go run internal/gen/gen_tlv_types.go -o tlv_types_generated.go + +func main() { + // This function is only here to satisfy the go:generate directive. + fmt.Println("Generating TLV type structures...") +} diff --git a/tlv/tlv_types_generated.go b/tlv/tlv_types_generated.go new file mode 100644 index 000000000..a18b74bb0 --- /dev/null +++ b/tlv/tlv_types_generated.go @@ -0,0 +1,811 @@ +// Code generated by tlv/internal/gen; DO NOT EDIT. + +package tlv + +type tlvType0 struct{} + +func (t *tlvType0) typeVal() Type { + return 0 +} + +type TlvType0 = *tlvType0 + +type tlvType1 struct{} + +func (t *tlvType1) typeVal() Type { + return 1 +} + +type TlvType1 = *tlvType1 + +type tlvType2 struct{} + +func (t *tlvType2) typeVal() Type { + return 2 +} + +type TlvType2 = *tlvType2 + +type tlvType3 struct{} + +func (t *tlvType3) typeVal() Type { + return 3 +} + +type TlvType3 = *tlvType3 + +type tlvType4 struct{} + +func (t *tlvType4) typeVal() Type { + return 4 +} + +type TlvType4 = *tlvType4 + +type tlvType5 struct{} + +func (t *tlvType5) typeVal() Type { + return 5 +} + +type TlvType5 = *tlvType5 + +type tlvType6 struct{} + +func (t *tlvType6) typeVal() Type { + return 6 +} + +type TlvType6 = *tlvType6 + +type tlvType7 struct{} + +func (t *tlvType7) typeVal() Type { + return 7 +} + +type TlvType7 = *tlvType7 + +type tlvType8 struct{} + +func (t *tlvType8) typeVal() Type { + return 8 +} + +type TlvType8 = *tlvType8 + +type tlvType9 struct{} + +func (t *tlvType9) typeVal() Type { + return 9 +} + +type TlvType9 = *tlvType9 + +type tlvType10 struct{} + +func (t *tlvType10) typeVal() Type { + return 10 +} + +type TlvType10 = *tlvType10 + +type tlvType11 struct{} + +func (t *tlvType11) typeVal() Type { + return 11 +} + +type TlvType11 = *tlvType11 + +type tlvType12 struct{} + +func (t *tlvType12) typeVal() Type { + return 12 +} + +type TlvType12 = *tlvType12 + +type tlvType13 struct{} + +func (t *tlvType13) typeVal() Type { + return 13 +} + +type TlvType13 = *tlvType13 + +type tlvType14 struct{} + +func (t *tlvType14) typeVal() Type { + return 14 +} + +type TlvType14 = *tlvType14 + +type tlvType15 struct{} + +func (t *tlvType15) typeVal() Type { + return 15 +} + +type TlvType15 = *tlvType15 + +type tlvType16 struct{} + +func (t *tlvType16) typeVal() Type { + return 16 +} + +type TlvType16 = *tlvType16 + +type tlvType17 struct{} + +func (t *tlvType17) typeVal() Type { + return 17 +} + +type TlvType17 = *tlvType17 + +type tlvType18 struct{} + +func (t *tlvType18) typeVal() Type { + return 18 +} + +type TlvType18 = *tlvType18 + +type tlvType19 struct{} + +func (t *tlvType19) typeVal() Type { + return 19 +} + +type TlvType19 = *tlvType19 + +type tlvType20 struct{} + +func (t *tlvType20) typeVal() Type { + return 20 +} + +type TlvType20 = *tlvType20 + +type tlvType21 struct{} + +func (t *tlvType21) typeVal() Type { + return 21 +} + +type TlvType21 = *tlvType21 + +type tlvType22 struct{} + +func (t *tlvType22) typeVal() Type { + return 22 +} + +type TlvType22 = *tlvType22 + +type tlvType23 struct{} + +func (t *tlvType23) typeVal() Type { + return 23 +} + +type TlvType23 = *tlvType23 + +type tlvType24 struct{} + +func (t *tlvType24) typeVal() Type { + return 24 +} + +type TlvType24 = *tlvType24 + +type tlvType25 struct{} + +func (t *tlvType25) typeVal() Type { + return 25 +} + +type TlvType25 = *tlvType25 + +type tlvType26 struct{} + +func (t *tlvType26) typeVal() Type { + return 26 +} + +type TlvType26 = *tlvType26 + +type tlvType27 struct{} + +func (t *tlvType27) typeVal() Type { + return 27 +} + +type TlvType27 = *tlvType27 + +type tlvType28 struct{} + +func (t *tlvType28) typeVal() Type { + return 28 +} + +type TlvType28 = *tlvType28 + +type tlvType29 struct{} + +func (t *tlvType29) typeVal() Type { + return 29 +} + +type TlvType29 = *tlvType29 + +type tlvType30 struct{} + +func (t *tlvType30) typeVal() Type { + return 30 +} + +type TlvType30 = *tlvType30 + +type tlvType31 struct{} + +func (t *tlvType31) typeVal() Type { + return 31 +} + +type TlvType31 = *tlvType31 + +type tlvType32 struct{} + +func (t *tlvType32) typeVal() Type { + return 32 +} + +type TlvType32 = *tlvType32 + +type tlvType33 struct{} + +func (t *tlvType33) typeVal() Type { + return 33 +} + +type TlvType33 = *tlvType33 + +type tlvType34 struct{} + +func (t *tlvType34) typeVal() Type { + return 34 +} + +type TlvType34 = *tlvType34 + +type tlvType35 struct{} + +func (t *tlvType35) typeVal() Type { + return 35 +} + +type TlvType35 = *tlvType35 + +type tlvType36 struct{} + +func (t *tlvType36) typeVal() Type { + return 36 +} + +type TlvType36 = *tlvType36 + +type tlvType37 struct{} + +func (t *tlvType37) typeVal() Type { + return 37 +} + +type TlvType37 = *tlvType37 + +type tlvType38 struct{} + +func (t *tlvType38) typeVal() Type { + return 38 +} + +type TlvType38 = *tlvType38 + +type tlvType39 struct{} + +func (t *tlvType39) typeVal() Type { + return 39 +} + +type TlvType39 = *tlvType39 + +type tlvType40 struct{} + +func (t *tlvType40) typeVal() Type { + return 40 +} + +type TlvType40 = *tlvType40 + +type tlvType41 struct{} + +func (t *tlvType41) typeVal() Type { + return 41 +} + +type TlvType41 = *tlvType41 + +type tlvType42 struct{} + +func (t *tlvType42) typeVal() Type { + return 42 +} + +type TlvType42 = *tlvType42 + +type tlvType43 struct{} + +func (t *tlvType43) typeVal() Type { + return 43 +} + +type TlvType43 = *tlvType43 + +type tlvType44 struct{} + +func (t *tlvType44) typeVal() Type { + return 44 +} + +type TlvType44 = *tlvType44 + +type tlvType45 struct{} + +func (t *tlvType45) typeVal() Type { + return 45 +} + +type TlvType45 = *tlvType45 + +type tlvType46 struct{} + +func (t *tlvType46) typeVal() Type { + return 46 +} + +type TlvType46 = *tlvType46 + +type tlvType47 struct{} + +func (t *tlvType47) typeVal() Type { + return 47 +} + +type TlvType47 = *tlvType47 + +type tlvType48 struct{} + +func (t *tlvType48) typeVal() Type { + return 48 +} + +type TlvType48 = *tlvType48 + +type tlvType49 struct{} + +func (t *tlvType49) typeVal() Type { + return 49 +} + +type TlvType49 = *tlvType49 + +type tlvType50 struct{} + +func (t *tlvType50) typeVal() Type { + return 50 +} + +type TlvType50 = *tlvType50 + +type tlvType51 struct{} + +func (t *tlvType51) typeVal() Type { + return 51 +} + +type TlvType51 = *tlvType51 + +type tlvType52 struct{} + +func (t *tlvType52) typeVal() Type { + return 52 +} + +type TlvType52 = *tlvType52 + +type tlvType53 struct{} + +func (t *tlvType53) typeVal() Type { + return 53 +} + +type TlvType53 = *tlvType53 + +type tlvType54 struct{} + +func (t *tlvType54) typeVal() Type { + return 54 +} + +type TlvType54 = *tlvType54 + +type tlvType55 struct{} + +func (t *tlvType55) typeVal() Type { + return 55 +} + +type TlvType55 = *tlvType55 + +type tlvType56 struct{} + +func (t *tlvType56) typeVal() Type { + return 56 +} + +type TlvType56 = *tlvType56 + +type tlvType57 struct{} + +func (t *tlvType57) typeVal() Type { + return 57 +} + +type TlvType57 = *tlvType57 + +type tlvType58 struct{} + +func (t *tlvType58) typeVal() Type { + return 58 +} + +type TlvType58 = *tlvType58 + +type tlvType59 struct{} + +func (t *tlvType59) typeVal() Type { + return 59 +} + +type TlvType59 = *tlvType59 + +type tlvType60 struct{} + +func (t *tlvType60) typeVal() Type { + return 60 +} + +type TlvType60 = *tlvType60 + +type tlvType61 struct{} + +func (t *tlvType61) typeVal() Type { + return 61 +} + +type TlvType61 = *tlvType61 + +type tlvType62 struct{} + +func (t *tlvType62) typeVal() Type { + return 62 +} + +type TlvType62 = *tlvType62 + +type tlvType63 struct{} + +func (t *tlvType63) typeVal() Type { + return 63 +} + +type TlvType63 = *tlvType63 + +type tlvType64 struct{} + +func (t *tlvType64) typeVal() Type { + return 64 +} + +type TlvType64 = *tlvType64 + +type tlvType65 struct{} + +func (t *tlvType65) typeVal() Type { + return 65 +} + +type TlvType65 = *tlvType65 + +type tlvType66 struct{} + +func (t *tlvType66) typeVal() Type { + return 66 +} + +type TlvType66 = *tlvType66 + +type tlvType67 struct{} + +func (t *tlvType67) typeVal() Type { + return 67 +} + +type TlvType67 = *tlvType67 + +type tlvType68 struct{} + +func (t *tlvType68) typeVal() Type { + return 68 +} + +type TlvType68 = *tlvType68 + +type tlvType69 struct{} + +func (t *tlvType69) typeVal() Type { + return 69 +} + +type TlvType69 = *tlvType69 + +type tlvType70 struct{} + +func (t *tlvType70) typeVal() Type { + return 70 +} + +type TlvType70 = *tlvType70 + +type tlvType71 struct{} + +func (t *tlvType71) typeVal() Type { + return 71 +} + +type TlvType71 = *tlvType71 + +type tlvType72 struct{} + +func (t *tlvType72) typeVal() Type { + return 72 +} + +type TlvType72 = *tlvType72 + +type tlvType73 struct{} + +func (t *tlvType73) typeVal() Type { + return 73 +} + +type TlvType73 = *tlvType73 + +type tlvType74 struct{} + +func (t *tlvType74) typeVal() Type { + return 74 +} + +type TlvType74 = *tlvType74 + +type tlvType75 struct{} + +func (t *tlvType75) typeVal() Type { + return 75 +} + +type TlvType75 = *tlvType75 + +type tlvType76 struct{} + +func (t *tlvType76) typeVal() Type { + return 76 +} + +type TlvType76 = *tlvType76 + +type tlvType77 struct{} + +func (t *tlvType77) typeVal() Type { + return 77 +} + +type TlvType77 = *tlvType77 + +type tlvType78 struct{} + +func (t *tlvType78) typeVal() Type { + return 78 +} + +type TlvType78 = *tlvType78 + +type tlvType79 struct{} + +func (t *tlvType79) typeVal() Type { + return 79 +} + +type TlvType79 = *tlvType79 + +type tlvType80 struct{} + +func (t *tlvType80) typeVal() Type { + return 80 +} + +type TlvType80 = *tlvType80 + +type tlvType81 struct{} + +func (t *tlvType81) typeVal() Type { + return 81 +} + +type TlvType81 = *tlvType81 + +type tlvType82 struct{} + +func (t *tlvType82) typeVal() Type { + return 82 +} + +type TlvType82 = *tlvType82 + +type tlvType83 struct{} + +func (t *tlvType83) typeVal() Type { + return 83 +} + +type TlvType83 = *tlvType83 + +type tlvType84 struct{} + +func (t *tlvType84) typeVal() Type { + return 84 +} + +type TlvType84 = *tlvType84 + +type tlvType85 struct{} + +func (t *tlvType85) typeVal() Type { + return 85 +} + +type TlvType85 = *tlvType85 + +type tlvType86 struct{} + +func (t *tlvType86) typeVal() Type { + return 86 +} + +type TlvType86 = *tlvType86 + +type tlvType87 struct{} + +func (t *tlvType87) typeVal() Type { + return 87 +} + +type TlvType87 = *tlvType87 + +type tlvType88 struct{} + +func (t *tlvType88) typeVal() Type { + return 88 +} + +type TlvType88 = *tlvType88 + +type tlvType89 struct{} + +func (t *tlvType89) typeVal() Type { + return 89 +} + +type TlvType89 = *tlvType89 + +type tlvType90 struct{} + +func (t *tlvType90) typeVal() Type { + return 90 +} + +type TlvType90 = *tlvType90 + +type tlvType91 struct{} + +func (t *tlvType91) typeVal() Type { + return 91 +} + +type TlvType91 = *tlvType91 + +type tlvType92 struct{} + +func (t *tlvType92) typeVal() Type { + return 92 +} + +type TlvType92 = *tlvType92 + +type tlvType93 struct{} + +func (t *tlvType93) typeVal() Type { + return 93 +} + +type TlvType93 = *tlvType93 + +type tlvType94 struct{} + +func (t *tlvType94) typeVal() Type { + return 94 +} + +type TlvType94 = *tlvType94 + +type tlvType95 struct{} + +func (t *tlvType95) typeVal() Type { + return 95 +} + +type TlvType95 = *tlvType95 + +type tlvType96 struct{} + +func (t *tlvType96) typeVal() Type { + return 96 +} + +type TlvType96 = *tlvType96 + +type tlvType97 struct{} + +func (t *tlvType97) typeVal() Type { + return 97 +} + +type TlvType97 = *tlvType97 + +type tlvType98 struct{} + +func (t *tlvType98) typeVal() Type { + return 98 +} + +type TlvType98 = *tlvType98 + +type tlvType99 struct{} + +func (t *tlvType99) typeVal() Type { + return 99 +} + +type TlvType99 = *tlvType99 + +type tlvType100 struct{} + +func (t *tlvType100) typeVal() Type { + return 100 +} + +type TlvType100 = *tlvType100