Net-2712/resource hcl parsing (#18250)

* Initial protohcl implementation

Co-authored-by: Matt Keeler <mkeeler@users.noreply.github.com>
Co-authored-by: Daniel Upton <daniel@floppy.co>

* resourcehcl: implement resource decoding on top of protohcl

Co-authored-by: Daniel Upton <daniel@floppy.co>

* fix: resolve ci failures

* test: add additional unmarshalling tests

* refactor: update function test to clean protohcl package imports

---------

Co-authored-by: Matt Keeler <mkeeler@users.noreply.github.com>
Co-authored-by: Daniel Upton <daniel@floppy.co>
This commit is contained in:
Poonam Jadhav 2023-08-11 15:52:51 -04:00 committed by GitHub
parent 4a0afb5d13
commit 559c61e6b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
50 changed files with 3709 additions and 0 deletions

6
go.mod
View File

@ -61,6 +61,7 @@ require (
github.com/hashicorp/go-version v1.2.1
github.com/hashicorp/golang-lru v0.5.4
github.com/hashicorp/hcl v1.0.0
github.com/hashicorp/hcl/v2 v2.6.0
github.com/hashicorp/hcp-scada-provider v0.2.3
github.com/hashicorp/hcp-sdk-go v0.55.0
github.com/hashicorp/hil v0.0.0-20200423225030-a18a1cd20038
@ -96,6 +97,7 @@ require (
github.com/ryanuber/columnize v2.1.2+incompatible
github.com/shirou/gopsutil/v3 v3.22.8
github.com/stretchr/testify v1.8.3
github.com/zclconf/go-cty v1.2.0
go.etcd.io/bbolt v1.3.7
go.opentelemetry.io/otel v1.16.0
go.opentelemetry.io/otel/metric v1.16.0
@ -138,6 +140,9 @@ require (
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
github.com/DataDog/datadog-go v4.8.2+incompatible // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
github.com/agext/levenshtein v1.2.1 // indirect
github.com/apparentlymart/go-textseg v1.0.0 // indirect
github.com/apparentlymart/go-textseg/v12 v12.0.0 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
github.com/benbjohnson/immutable v0.4.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
@ -207,6 +212,7 @@ require (
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect

23
go.sum
View File

@ -111,6 +111,8 @@ github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdko
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af h1:DBNMBMuMiWYu0b+8KMJuWmfCkcxl09JwdlqwDZZ6U14=
github.com/abdullin/seq v0.0.0-20160510034733-d5467c17e7af/go.mod h1:5Jv4cbFiHJMsVxt52+i0Ha45fjshj6wxYr1r19tB9bw=
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
@ -118,6 +120,11 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF
github.com/aliyun/alibaba-cloud-sdk-go v1.62.156 h1:K4N91T1+RlSlx+t2dujeDviy4ehSGVjEltluDgmeHS4=
github.com/aliyun/alibaba-cloud-sdk-go v1.62.156/go.mod h1:Api2AkmMgGaSUAhmk76oaFObkoeCPc/bKAqcyplPODs=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
github.com/apparentlymart/go-textseg v1.0.0 h1:rRmlIsPEEhUTIKQb7T++Nz/A5Q6C9IuX2wFoYVvnCs0=
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
github.com/apparentlymart/go-textseg/v12 v12.0.0 h1:bNEQyAGak9tojivJNkoqWErVCQbjdL7GzRt3F8NvfJ0=
github.com/apparentlymart/go-textseg/v12 v12.0.0/go.mod h1:S/4uRK2UtaQttw1GenVJEynmyUenKwP++x/+DdGV/Ec=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e h1:QEF07wC0T1rKkctt1RINW/+RMTVmiwxETico2l3gxJA=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@ -312,6 +319,7 @@ github.com/go-ozzo/ozzo-validation v3.6.0+incompatible/go.mod h1:gsEKFIVnabGBt6m
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-test/deep v1.0.2/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg=
github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0=
@ -367,6 +375,7 @@ github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@ -552,6 +561,8 @@ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+l
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/hcl/v2 v2.6.0 h1:3krZOfGY6SziUXa6H9PJU6TyohHn7I+ARYnhbeNBz+o=
github.com/hashicorp/hcl/v2 v2.6.0/go.mod h1:bQTN5mpo+jewjJgh8jr0JUguIi7qPHUF6yIfAEN3jqY=
github.com/hashicorp/hcp-scada-provider v0.2.3 h1:AarYR+/Pcv+cMvPdAlb92uOBmZfEH6ny4+DT+4NY2VQ=
github.com/hashicorp/hcp-scada-provider v0.2.3/go.mod h1:ZFTgGwkzNv99PLQjTsulzaCplCzOTBh0IUQsPKzrQFo=
github.com/hashicorp/hcp-sdk-go v0.55.0 h1:T4sQtgQfQJOD0uucT4hS+GZI1FmoHAQMADj277W++xw=
@ -653,6 +664,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/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/linode/linodego v0.7.1/go.mod h1:ga11n3ivecUrPCHN0rANxKmfWBJVkOXfLMZinAbj2sY=
github.com/linode/linodego v0.10.0 h1:AMdb82HVgY8o3mjBXJcUv9B+fnJjfDMn2rNRGbX+jvM=
@ -710,6 +723,8 @@ github.com/mitchellh/go-testing-interface v0.0.0-20171004221916-a61a99592b77/go.
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/go-testing-interface v1.14.0 h1:/x0XQ6h+3U3nAyk1yx+bHPURrKa9sVVvYbuqZ7pIAtI=
github.com/mitchellh/go-testing-interface v1.14.0/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8=
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452 h1:hOY53G+kBFhbYFpRVxHl5eS7laP6B1+Cq+Z9Dry1iMU=
github.com/mitchellh/hashstructure v0.0.0-20170609045927-2bca23e0e452/go.mod h1:QjSHrPWS+BGUVBYkbTZWEnOh3G1DutKwClXU/ABz6AQ=
@ -847,6 +862,7 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529 h1:nn5Wsu0esKSJiIVhscUt
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/fasthash v1.0.3 h1:EI9+KE1EwvMLBWwjpRDc+fEM+prwxDYbslddQGtrmhM=
github.com/segmentio/fasthash v1.0.3/go.mod h1:waKX8l2N8yckOgmSsXJi7x1ZfdKZ4x7KRMzBtS3oedY=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.22.8 h1:a4s3hXogo5mE2PfdfJIonDbstO/P+9JszdfhAHSzD9Y=
github.com/shirou/gopsutil/v3 v3.22.8/go.mod h1:s648gW4IywYzUfE/KjXxUsqrqx/T2xO5VqOXxONeRfI=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
@ -871,6 +887,7 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
@ -912,6 +929,7 @@ github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVK
github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmware/govmomi v0.18.0 h1:f7QxSmP7meCtoAmiKZogvVbLInT+CZx6Px6K5rYsJZo=
github.com/vmware/govmomi v0.18.0/go.mod h1:URlwyTFZX72RmxtxuaFL2Uj3fD1JTvZdx59bHWk6aFU=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
@ -930,6 +948,8 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
github.com/zclconf/go-cty v1.2.0 h1:sPHsy7ADcIZQP3vILvTjrh74ZA175TFP5vqiNK1UmlI=
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
@ -974,6 +994,7 @@ golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190422162423-af44ce270edf/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@ -1035,6 +1056,7 @@ golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20180530234432-1e491301e022/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180611182652-db08ff08e862/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1137,6 +1159,7 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190523142557-0e01d883c5c5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

114
internal/protohcl/any.go Normal file
View File

@ -0,0 +1,114 @@
package protohcl
import (
"fmt"
"strings"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/reflect/protoregistry"
"google.golang.org/protobuf/types/known/anypb"
)
const wellKnownTypeAny = "google.protobuf.Any"
type AnyTypeProvider interface {
AnyType(*UnmarshalContext, MessageDecoder) (protoreflect.FullName, MessageDecoder, error)
}
type AnyTypeURLProvider struct {
TypeURLFieldName string
}
func (p *AnyTypeURLProvider) AnyType(ctx *UnmarshalContext, decoder MessageDecoder) (protoreflect.FullName, MessageDecoder, error) {
typeURLFieldName := "type_url"
if p != nil {
typeURLFieldName = p.TypeURLFieldName
}
var typeURL *IterField
err := decoder.EachField(FieldIterator{
Desc: (&anypb.Any{}).ProtoReflect().Descriptor(),
Func: func(field *IterField) error {
if field.Name == typeURLFieldName {
typeURL = field
}
return nil
},
IgnoreUnknown: true,
})
if err != nil {
return "", nil, err
}
if typeURL == nil || typeURL.Val == nil {
return "", nil, fmt.Errorf("%s field is required to decode Any", typeURLFieldName)
}
url, err := stringFromCty(*typeURL.Val)
if err != nil {
return "", nil, err
}
slashIdx := strings.LastIndex(url, "/")
typeName := url
// strip all "hostname" parts of the URL path
if slashIdx > 1 && slashIdx+1 < len(url) {
typeName = url[slashIdx+1:]
}
return protoreflect.FullName(typeName), decoder.SkipFields(typeURLFieldName), nil
}
func (u UnmarshalOptions) decodeAny(ctx *UnmarshalContext, decoder MessageDecoder, msg protoreflect.Message) error {
var typeProvider AnyTypeProvider = &AnyTypeURLProvider{TypeURLFieldName: "type_url"}
if u.AnyTypeProvider != nil {
typeProvider = u.AnyTypeProvider
}
var (
typeName protoreflect.FullName
err error
)
typeName, decoder, err = typeProvider.AnyType(ctx, decoder)
if err != nil {
return fmt.Errorf("error getting type for Any field: %w", err)
}
// the type.googleapis.come/ should be optional
mt, err := protoregistry.GlobalTypes.FindMessageByName(typeName)
if err != nil {
return fmt.Errorf("error looking up type information for %s: %w", typeName, err)
}
newMsg := mt.New()
err = u.decodeMessage(&UnmarshalContext{
Parent: ctx.Parent,
Name: ctx.Name,
Message: newMsg,
}, decoder, newMsg)
if err != nil {
return err
}
enc, err := proto.Marshal(newMsg.Interface())
if err != nil {
return fmt.Errorf("error marshalling Any data as protobuf value: %w", err)
}
anyValue := msg.Interface().(*anypb.Any)
// This will look like <proto package>.<proto Message name> and not quite like a full URL with a path
anyValue.TypeUrl = string(newMsg.Descriptor().FullName())
anyValue.Value = enc
return nil
}
func isAnyField(desc protoreflect.FieldDescriptor) bool {
if desc.Kind() != protoreflect.MessageKind {
return false
}
return desc.Message().FullName() == wellKnownTypeAny
}

View File

@ -0,0 +1,154 @@
package protohcl
import (
"fmt"
"github.com/pkg/errors"
"github.com/zclconf/go-cty/cty"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
)
func (u UnmarshalOptions) decodeAttribute(ctx *UnmarshalContext, newMessage newMessageFn, f protoreflect.FieldDescriptor, val cty.Value, listAllowed bool) (protoreflect.Value, error) {
if f.IsMap() {
return u.decodeAttributeToMap(ctx, newMessage, f, val)
}
if f.IsList() && listAllowed {
return u.decodeAttributeToList(ctx, newMessage, f, val)
}
ok, value, err := decodeAttributeToWellKnownType(f, val)
if ok {
return value, errors.Wrapf(err, "%s: Failed to unmarshal argument %s", ctx.ErrorRange(), ctx.Name)
}
ok, value, err = u.decodeAttributeToMessage(ctx, newMessage, f, val)
if ok {
return value, err
}
value, err = decodeAttributeToPrimitive(f, val)
if err != nil {
return value, errors.Wrapf(err, "%s: Failed to unmarshal argument %s", ctx.ErrorRange(), ctx.Name)
}
return value, nil
}
func (u UnmarshalOptions) decodeAttributeToMessage(ctx *UnmarshalContext, newMessage newMessageFn, desc protoreflect.FieldDescriptor, val cty.Value) (bool, protoreflect.Value, error) {
if desc.Kind() != protoreflect.MessageKind {
return false, protoreflect.Value{}, nil
}
msg := newMessage().Message()
ctx = &UnmarshalContext{
Parent: ctx.Parent,
Name: ctx.Name,
Message: msg,
Range: ctx.Range,
}
// We have limited support for HCL functions, essentially just those that
// return a protobuf message (like the resource `gvk` function) in which
// case, the message will be wrapped in a cty capsule.
if val.Type().IsCapsuleType() {
msg, ok := val.EncapsulatedValue().(proto.Message)
if ok {
return true, protoreflect.ValueOf(msg.ProtoReflect()), nil
} else {
return true, protoreflect.Value{}, fmt.Errorf("expected encapsulated value to be a message, actual type: %T", val.EncapsulatedValue())
}
}
if !val.Type().IsObjectType() {
return false, protoreflect.Value{}, nil
}
decoder := newObjectDecoder(val, u.FieldNamer, ctx.ErrorRange())
if err := u.decodeMessage(ctx, decoder, msg); err != nil {
return true, protoreflect.Value{}, err
}
return true, protoreflect.ValueOf(msg), nil
}
func (u UnmarshalOptions) decodeAttributeToList(ctx *UnmarshalContext, newMessage newMessageFn, desc protoreflect.FieldDescriptor, value cty.Value) (protoreflect.Value, error) {
if value.IsNull() {
return protoreflect.Value{}, nil
}
valueType := value.Type()
if !valueType.IsListType() && !valueType.IsTupleType() {
return protoreflect.Value{}, fmt.Errorf("expected list/tuple type after HCL decode but the actual type was %s", valueType.FriendlyName())
}
if value.LengthInt() < 1 {
return protoreflect.Value{}, nil
}
protoList := newMessage().List()
var err error
var idx int
value.ForEachElement(func(_ cty.Value, val cty.Value) bool {
var protoVal protoreflect.Value
protoVal, err = u.decodeAttribute(&UnmarshalContext{
Parent: ctx,
Name: fmt.Sprintf("%s[%d]", u.FieldNamer.NameField(desc), idx),
}, protoList.NewElement, desc, val, false)
if err != nil {
return true
}
idx++
protoList.Append(protoVal)
return false
})
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfList(protoList), nil
}
func (u UnmarshalOptions) decodeAttributeToMap(ctx *UnmarshalContext, newMessage newMessageFn, desc protoreflect.FieldDescriptor, value cty.Value) (protoreflect.Value, error) {
if value.IsNull() {
return protoreflect.Value{}, nil
}
valueType := value.Type()
if !valueType.IsMapType() && !valueType.IsObjectType() {
return protoreflect.Value{}, fmt.Errorf("expected map/object type after HCL decode but the actual type was %s", valueType.FriendlyName())
}
if value.LengthInt() < 1 {
return protoreflect.Value{}, nil
}
protoMap := newMessage().Map()
protoValueDesc := desc.MapValue()
var err error
value.ForEachElement(func(key cty.Value, val cty.Value) (stop bool) {
var protoVal protoreflect.Value
protoVal, err = u.decodeAttribute(&UnmarshalContext{
Parent: ctx,
Name: fmt.Sprintf("%s[%q]", u.FieldNamer.NameField(desc), key.AsString()),
Message: nil, // TODO: what should this really be?
}, protoMap.NewValue, protoValueDesc, val, false)
if err != nil {
return true
}
if protoVal.IsValid() {
// HCL doesn't support non-string keyed maps so we blindly use string keys
protoMap.Set(protoreflect.ValueOfString(key.AsString()).MapKey(), protoVal)
}
return false
})
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfMap(protoMap), nil
}

112
internal/protohcl/blocks.go Normal file
View File

@ -0,0 +1,112 @@
package protohcl
import (
"fmt"
"github.com/hashicorp/hcl/v2"
"google.golang.org/protobuf/reflect/protoreflect"
)
func (u UnmarshalOptions) decodeBlocks(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) {
if f.Kind() != protoreflect.MessageKind {
return protoreflect.Value{}, fmt.Errorf("only protobuf message kinds can use HCL block syntax")
}
if f.IsMap() {
return u.decodeBlocksToMap(ctx, blocks, msg, f)
}
if f.IsList() {
return u.decodeBlocksToList(ctx, blocks, msg, f)
}
return u.decodeBlocksToMessage(ctx, blocks, msg, f)
}
func (u UnmarshalOptions) decodeBlocksToMap(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) {
val := msg.NewField(f)
mapVal := val.Map()
for _, block := range blocks {
if len(block.Labels) != 1 {
return protoreflect.Value{}, fmt.Errorf("protobuf map fields must have 1 HCL block label")
}
key := protoreflect.ValueOfString(block.Labels[0])
value := mapVal.NewValue()
msgVal := value.Message()
err := u.decodeMessage(
&UnmarshalContext{
Parent: ctx,
Name: fmt.Sprintf("%s[%q]", u.FieldNamer.NameField(f), block.Labels[0]),
Message: msgVal,
Range: block.DefRange,
},
u.bodyDecoder(block.Body),
msgVal,
)
if err != nil {
return protoreflect.Value{}, err
}
mapVal.Set(key.MapKey(), value)
}
return val, nil
}
func (u UnmarshalOptions) decodeBlocksToList(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) {
val := msg.NewField(f)
listVal := val.List()
var err error
for idx, block := range blocks {
if len(block.Labels) > 0 {
return protoreflect.Value{}, fmt.Errorf("repeated protobuf fields must not have HCL block labels")
}
elem := listVal.NewElement()
elemMsg := elem.Message()
err = u.decodeMessage(
&UnmarshalContext{
Parent: ctx,
Name: fmt.Sprintf("%s[%d]", u.FieldNamer.NameField(f), idx),
Message: elemMsg,
Range: block.DefRange,
},
u.bodyDecoder(block.Body),
elemMsg,
)
if err != nil {
return protoreflect.Value{}, err
}
listVal.Append(elem)
}
return val, nil
}
func (u UnmarshalOptions) decodeBlocksToMessage(ctx *UnmarshalContext, blocks hcl.Blocks, msg protoreflect.Message, f protoreflect.FieldDescriptor) (protoreflect.Value, error) {
if len(blocks) > 1 {
return protoreflect.Value{}, fmt.Errorf("only one HCL block may be specified for a non-repeated protobuf Message")
}
val := msg.NewField(f)
valMsg := val.Message()
err := u.decodeMessage(
&UnmarshalContext{
Parent: ctx,
Name: blocks[0].Type,
Message: valMsg,
Range: blocks[0].DefRange,
},
u.bodyDecoder(blocks[0].Body),
valMsg,
)
if err != nil {
return protoreflect.Value{}, err
}
return val, nil
}

146
internal/protohcl/cty.go Normal file
View File

@ -0,0 +1,146 @@
package protohcl
import (
"encoding/base64"
"fmt"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/gocty"
)
func boolFromCty(val cty.Value) (bool, error) {
if val.Type() != cty.Bool {
return false, fmt.Errorf("expected value of type %s but actual type is %s", cty.Bool.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return false, nil
}
return val.True(), nil
}
func int32FromCty(val cty.Value) (int32, error) {
if val.Type() != cty.Number {
return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return 0, nil
}
var goVal int32
if err := gocty.FromCtyValue(val, &goVal); err != nil {
return 0, fmt.Errorf("error converting cty value of type %s to int32: %w", val.Type().FriendlyName(), err)
}
return goVal, nil
}
func uint32FromCty(val cty.Value) (uint32, error) {
if val.Type() != cty.Number {
return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return 0, nil
}
var goVal uint32
if err := gocty.FromCtyValue(val, &goVal); err != nil {
return 0, fmt.Errorf("error converting cty value of type %s to uint32: %w", val.Type().FriendlyName(), err)
}
return goVal, nil
}
func int64FromCty(val cty.Value) (int64, error) {
if val.Type() != cty.Number {
return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return 0, nil
}
var goVal int64
if err := gocty.FromCtyValue(val, &goVal); err != nil {
return 0, fmt.Errorf("error converting cty value of type %s to int64: %w", val.Type().FriendlyName(), err)
}
return goVal, nil
}
func uint64FromCty(val cty.Value) (uint64, error) {
if val.Type() != cty.Number {
return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return 0, nil
}
var goVal uint64
if err := gocty.FromCtyValue(val, &goVal); err != nil {
return 0, fmt.Errorf("error converting cty value of type %s to uint64: %w", val.Type().FriendlyName(), err)
}
return goVal, nil
}
func floatFromCty(val cty.Value) (float32, error) {
if val.Type() != cty.Number {
return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return 0, nil
}
var goVal float32
if err := gocty.FromCtyValue(val, &goVal); err != nil {
return 0, fmt.Errorf("error converting cty value of type %s to float32: %w", val.Type().FriendlyName(), err)
}
return goVal, nil
}
func doubleFromCty(val cty.Value) (float64, error) {
if val.Type() != cty.Number {
return 0, fmt.Errorf("expected value of type %s but actual type is %s", cty.Number.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return 0, nil
}
var goVal float64
if err := gocty.FromCtyValue(val, &goVal); err != nil {
return 0, fmt.Errorf("error converting cty value of type %s to float64: %w", val.Type().FriendlyName(), err)
}
return goVal, nil
}
func stringFromCty(val cty.Value) (string, error) {
if val.Type() != cty.String {
return "", fmt.Errorf("expected value of type %s but actual type is %s", cty.String.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return "", nil
}
return val.AsString(), nil
}
func bytesFromCty(val cty.Value) ([]byte, error) {
if val.Type() != cty.String {
return nil, fmt.Errorf("expected value of type %s but actual type is %s", cty.String.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
return nil, nil
}
encoded := val.AsString()
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
return nil, fmt.Errorf("error base64 decoding byte string: %w", err)
}
return decoded, nil
}

View File

@ -0,0 +1,284 @@
package protohcl
import (
"fmt"
"sort"
"github.com/hashicorp/hcl/v2"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
"google.golang.org/protobuf/reflect/protoreflect"
)
// MessageDecoder provides an abstract way to decode protobuf messages from HCL
// blocks or objects.
type MessageDecoder interface {
// EachField calls the given iterator for each field provided in the HCL source.
EachField(iter FieldIterator) error
// SkipFields returns a MessageDecoder that skips over the given fields. It is
// primarily used for doing two-pass decoding of protobuf `Any` fields.
SkipFields(fields ...string) MessageDecoder
}
// IterField represents a field discovered by the MessageDecoder.
type IterField struct {
// Name is the HCL name of the field.
Name string
// Desc is the protobuf field descriptor.
Desc protoreflect.FieldDescriptor
// Val is the field value, only if it was given using HCL attribute syntax.
Val *cty.Value
// Blocks contains the HCL blocks that were given for this field.
Blocks []*hcl.Block
// Range determines where in the HCL source the field was given, it is useful
// for error messages.
Range hcl.Range
}
// FieldIterator is given to MessageDecoder.EachField to iterate over all of the
// fields in a given HCL block or object.
type FieldIterator struct {
// IgnoreUnknown instructs the MessageDecoder to skip over any fields not
// included in Desc.
IgnoreUnknown bool
// Desc is the protobuf descriptor for the message the caller is decoding into.
// It is used to determine which fields are valid.
Desc protoreflect.MessageDescriptor
// Func is called for each field in the given HCL block or object.
Func func(field *IterField) error
}
func newBodyDecoder(
body hcl.Body,
namer FieldNamer,
functions map[string]function.Function,
) MessageDecoder {
return bodyDecoder{
body: body,
namer: namer,
functions: functions,
skipFields: make(map[string]struct{}),
}
}
type bodyDecoder struct {
body hcl.Body
namer FieldNamer
functions map[string]function.Function
skipFields map[string]struct{}
}
func (bd bodyDecoder) EachField(iter FieldIterator) error {
schema, err := bd.schema(iter.Desc)
if err != nil {
return err
}
var (
content *hcl.BodyContent
diags hcl.Diagnostics
)
if iter.IgnoreUnknown {
content, _, diags = bd.body.PartialContent(schema)
} else {
content, diags = bd.body.Content(schema)
}
if diags.HasErrors() {
return diags
}
fields := make([]*IterField, 0)
for _, attr := range content.Attributes {
if _, ok := bd.skipFields[attr.Name]; ok {
continue
}
desc := bd.namer.GetField(iter.Desc.Fields(), attr.Name)
val, err := attr.Expr.Value(&hcl.EvalContext{Functions: bd.functions})
if err != nil {
return err
}
fields = append(fields, &IterField{
Name: attr.Name,
Desc: desc,
Val: &val,
Range: attr.Expr.Range(),
})
}
for blockType, blocks := range content.Blocks.ByType() {
if _, ok := bd.skipFields[blockType]; ok {
continue
}
desc := bd.namer.GetField(iter.Desc.Fields(), blockType)
fields = append(fields, &IterField{
Name: blockType,
Desc: desc,
Blocks: blocks,
})
}
// Always handle Any fields last, as decoding them may require type information
// gathered from other fields (e.g. as in the case of Resource GVKs).
sort.Slice(fields, func(a, b int) bool {
if isAnyField(fields[b].Desc) && !isAnyField(fields[a].Desc) {
return true
}
return a < b
})
for _, field := range fields {
if err := iter.Func(field); err != nil {
return err
}
}
return nil
}
func (bd bodyDecoder) SkipFields(fields ...string) MessageDecoder {
skip := make(map[string]struct{}, len(fields)+len(bd.skipFields))
for k, v := range bd.skipFields {
skip[k] = v
}
for _, field := range fields {
skip[field] = struct{}{}
}
// Note: we rely on the fact bd isn't a pointer to copy the struct here.
bd.skipFields = skip
return bd
}
func (bd bodyDecoder) schema(desc protoreflect.MessageDescriptor) (*hcl.BodySchema, error) {
var schema hcl.BodySchema
fields := desc.Fields()
for i := 0; i < fields.Len(); i++ {
f := fields.Get(i)
kind := f.Kind()
// maps are special and whether they use block or attribute syntax depends
// on the value type
if f.IsMap() {
valueDesc := f.MapValue()
valueKind := valueDesc.Kind()
wktHint := wellKnownTypeSchemaHint(valueDesc)
// Message types should generally be encoded as blocks unless its a special Well Known Type
// that should use attribute encoding
if valueKind == protoreflect.MessageKind && wktHint != wellKnownAttribute {
schema.Blocks = append(schema.Blocks, hcl.BlockHeaderSchema{
Type: bd.namer.NameField(f),
LabelNames: []string{"key"},
})
continue
}
// non-message types or Well Known Message types that need attribute encoding
// get decoded as attributes
schema.Attributes = append(schema.Attributes, hcl.AttributeSchema{
Name: bd.namer.NameField(f),
})
continue
}
wktHint := wellKnownTypeSchemaHint(f)
// message types generally will use block syntax unless its a well known
// message type that requires attribute syntax specifically.
if kind == protoreflect.MessageKind && wktHint != wellKnownAttribute {
schema.Blocks = append(schema.Blocks, hcl.BlockHeaderSchema{
Type: bd.namer.NameField(f),
})
}
// by default use attribute encoding
// - primitives
// - repeated primitives
// - Well Known Types requiring attribute syntax
// - repeated Well Known Types requiring attribute syntax
schema.Attributes = append(schema.Attributes, hcl.AttributeSchema{
Name: bd.namer.NameField(f),
})
continue
}
// Add skipped fields to the schema so HCL doesn't throw an error when it finds them.
for field := range bd.skipFields {
schema.Attributes = append(schema.Attributes, hcl.AttributeSchema{Name: field})
schema.Blocks = append(schema.Blocks, hcl.BlockHeaderSchema{Type: field})
}
return &schema, nil
}
func newObjectDecoder(object cty.Value, namer FieldNamer, rng hcl.Range) MessageDecoder {
return objectDecoder{
object: object,
namer: namer,
rng: rng,
skipFields: make(map[string]struct{}),
}
}
type objectDecoder struct {
object cty.Value
namer FieldNamer
rng hcl.Range
skipFields map[string]struct{}
}
func (od objectDecoder) EachField(iter FieldIterator) error {
for attr := range od.object.Type().AttributeTypes() {
if _, ok := od.skipFields[attr]; ok {
continue
}
desc := od.namer.GetField(iter.Desc.Fields(), attr)
if desc == nil {
if iter.IgnoreUnknown {
continue
} else {
return fmt.Errorf("%s: Unsupported argument; An argument named %q is not expected here.", od.rng, attr)
}
}
val := od.object.GetAttr(attr)
if err := iter.Func(&IterField{
Name: attr,
Desc: desc,
Val: &val,
}); err != nil {
return err
}
}
return nil
}
func (od objectDecoder) SkipFields(fields ...string) MessageDecoder {
skip := make(map[string]struct{}, len(fields)+len(od.skipFields))
for k, v := range od.skipFields {
skip[k] = v
}
for _, field := range fields {
skip[field] = struct{}{}
}
// Note: we rely on the fact od isn't a pointer to copy the struct here.
od.skipFields = skip
return od
}

76
internal/protohcl/doc.go Normal file
View File

@ -0,0 +1,76 @@
// The protohcl package aims to define a canonical way to translate between
// protobuf and HCL encodings of data.
//
// Similar to google.golang.org/protobuf/encoding/protojson it intends to be
// opinionated about what the canonical HCL representation of a protobuf type
// should be.
//
// As HCL is a user centric data format as opposed to JSON/Protobuf which
// are intended to be used more by machines, efficiency is not a primary goal
// of this package as it is expected that users are either doing the encoding to and
// decoding from HCL at the edge (such as within the Consul CLI) or that even
// when done on servers, the rate that servers perform these translations should
// be low enough to have any inefficiency produce a tangible performance impact.
//
// HCL has two different syntaxes that could be used to represent data: attribute and block
//
// This implementation chooses to represent primitive values, enums and the well known wrapper types and
// collections of these values (maps and repeated fields) with attribute syntax. Other messages and collections
// with message value types will be represented with block syntax for example
//
// message Foo {
// map<string, int32> map_of_ints = 1;
// map<string, OtherMessage> map_of_messages = 2;
// }
//
// would have HCL like:
//
// map_of_ints = {
// "foo": 1,
// "bar": 2,
// }
// map_of_messages "foo" {
// ...other fields
// }
// map_of_messages "bar" {
// ...other fields
// }
//
// Similar goes for list of primitives vs list of messages (except the block syntax uses no labels). The differences
// between primitive fields outside of a collection and a message field really just amounts to not having to specify
// the "=" between the field name and the "{" character.
//
// Field Mapping
// | proto3 | HCL Type | example | notes |
// |------------------------+---------------+---------+---------------------------------------------------------------------------------+
// | message | Object | | Represented as a block |
// | enum | String | | |
// | map<K,V> | Map | | All keys are converted to/from strings. |
// | repeated V | List | | |
// | bool | Bool | | |
// | string | String | | |
// | bytes | base64 String | | |
// | int32, fixed32, uint32 | Number | | |
// | int64, fixed64, uint64 | Number | | |
// | float, double | Number | | |
//
// ----- Well Known Types -----
//
// | Any | Object | | |
// | Timestamp | String | | RFC 3339 compliant |
// | Duration | String | | String form is what would be accepted by time.ParseDuration |
// | Struct | Map | | |
// | Empty | Object | | An object with no fields |
// | BoolValue | Bool | | Mostly the same as a regular bool except null values in the HCL are preserved |
// | BytesValue | Bytes | | Mostly the same as a regular bytes except null values in the HCL are preserved |
// | StringValue | String | | Mostly the same as a regular string except null values in the HCL are preserved |
// | FloatValue | Number | | Mostly the same as a regular float except null values in the HCL are preserved |
// | DoubleValue | Number | | Mostly the same as a regular double except null values in the HCL are preserved |
// | Int32Value | Number | | Mostly the same as a regular int32 except null values in the HCL are preserved |
// | UInt32Value | Number | | Mostly the same as a regular uint32 except null values in the HCL are preserved |
// | Int64Value | Number | | Mostly the same as a regular int64 except null values in the HCL are preserved |
// | UInt64Value | Number | | Mostly the same as a regular uint64 except null values in the HCL are preserved |
// | FieldMask | String | | Each string of the FieldMask will be joined with a '.' |
//
package protohcl

View File

@ -0,0 +1,18 @@
package protohcl
import "google.golang.org/protobuf/reflect/protoreflect"
type FieldNamer interface {
NameField(protoreflect.FieldDescriptor) string
GetField(protoreflect.FieldDescriptors, string) protoreflect.FieldDescriptor
}
type textFieldNamer struct{}
func (textFieldNamer) NameField(fd protoreflect.FieldDescriptor) string {
return fd.TextName()
}
func (textFieldNamer) GetField(fds protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor {
return fds.ByTextName(name)
}

View File

@ -0,0 +1,51 @@
package protohcl
import (
"fmt"
"strings"
"google.golang.org/protobuf/reflect/protoreflect"
)
type oneOfTracker struct {
namer FieldNamer
set map[protoreflect.FullName]string
}
func newOneOfTracker(namer FieldNamer) *oneOfTracker {
return &oneOfTracker{
namer: namer,
set: make(map[protoreflect.FullName]string),
}
}
func (o *oneOfTracker) markFieldAsSet(desc protoreflect.FieldDescriptor) error {
oneof := desc.ContainingOneof()
if oneof == nil {
return nil
}
oneOfName := oneof.FullName()
if otherFieldName, ok := o.set[oneOfName]; ok {
oneOfFields := oneof.Fields()
var builder strings.Builder
for i := 0; i < oneOfFields.Len(); i++ {
name := o.namer.NameField(oneOfFields.Get(i))
if i == oneOfFields.Len()-1 {
builder.WriteString(fmt.Sprintf("%q", name))
} else if i == oneOfFields.Len()-2 {
builder.WriteString(fmt.Sprintf("%q and ", name))
} else {
builder.WriteString(fmt.Sprintf("%q, ", name))
}
}
return fmt.Errorf("Cannot set %q because %q was previously set. Only one of %s may be set.", o.namer.NameField(desc), otherFieldName, builder.String())
}
o.set[oneOfName] = o.namer.NameField(desc)
return nil
}

View File

@ -0,0 +1,138 @@
package protohcl
import (
"fmt"
"github.com/zclconf/go-cty/cty"
"google.golang.org/protobuf/reflect/protoreflect"
)
func decodeAttributeToPrimitive(desc protoreflect.FieldDescriptor, val cty.Value) (protoreflect.Value, error) {
switch kind := desc.Kind(); kind {
case protoreflect.BoolKind:
return protoBoolFromCty(val)
case protoreflect.EnumKind:
return protoEnumFromCty(desc, val)
case protoreflect.Int32Kind:
return protoInt32FromCty(val)
case protoreflect.Sint32Kind:
return protoInt32FromCty(val)
case protoreflect.Uint32Kind:
return protoUint32FromCty(val)
case protoreflect.Int64Kind:
return protoInt64FromCty(val)
case protoreflect.Sint64Kind:
return protoInt64FromCty(val)
case protoreflect.Uint64Kind:
return protoUint64FromCty(val)
case protoreflect.Sfixed32Kind:
return protoInt32FromCty(val)
case protoreflect.Fixed32Kind:
return protoUint32FromCty(val)
case protoreflect.FloatKind:
return protoFloatFromCty(val)
case protoreflect.Sfixed64Kind:
return protoInt64FromCty(val)
case protoreflect.Fixed64Kind:
return protoUint64FromCty(val)
case protoreflect.DoubleKind:
return protoDoubleFromCty(val)
case protoreflect.StringKind:
return protoStringFromCty(val)
case protoreflect.BytesKind:
return protoBytesFromCty(val)
default:
return protoreflect.Value{}, fmt.Errorf("unknown primitive protobuf kind: %q", kind.String())
}
}
func protoBoolFromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := boolFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfBool(goVal), nil
}
func protoEnumFromCty(desc protoreflect.FieldDescriptor, val cty.Value) (protoreflect.Value, error) {
if val.Type() != cty.String {
return protoreflect.Value{}, fmt.Errorf("expected value of type %s but actual type is %s", cty.String.FriendlyName(), val.Type().FriendlyName())
}
if val.IsNull() {
defaultValDesc := desc.DefaultEnumValue()
return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil
}
valDesc := desc.Enum().Values().ByName(protoreflect.Name(val.AsString()))
if valDesc == nil {
defaultValDesc := desc.DefaultEnumValue()
return protoreflect.ValueOfEnum(defaultValDesc.Number()), nil
}
return protoreflect.ValueOfEnum(valDesc.Number()), nil
}
func protoInt32FromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := int32FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfInt32(goVal), nil
}
func protoUint32FromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := uint32FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfUint32(goVal), nil
}
func protoInt64FromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := int64FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfInt64(goVal), nil
}
func protoUint64FromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := uint64FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfUint64(goVal), nil
}
func protoFloatFromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := floatFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfFloat32(goVal), nil
}
func protoDoubleFromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := doubleFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfFloat64(goVal), nil
}
func protoStringFromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := stringFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfString(goVal), nil
}
func protoBytesFromCty(val cty.Value) (protoreflect.Value, error) {
goVal, err := bytesFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfBytes(goVal), nil
}

View File

@ -0,0 +1,9 @@
version: v1
managed:
enabled: true
go_package_prefix:
default: github.com/hashicorp/consul/internal/protohcl/testproto
plugins:
- name: go
out: .
opt: paths=source_relative

View File

@ -0,0 +1,994 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.30.0
// protoc (unknown)
// source: example.proto
package testproto
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
anypb "google.golang.org/protobuf/types/known/anypb"
durationpb "google.golang.org/protobuf/types/known/durationpb"
emptypb "google.golang.org/protobuf/types/known/emptypb"
structpb "google.golang.org/protobuf/types/known/structpb"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
wrapperspb "google.golang.org/protobuf/types/known/wrapperspb"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type Protocol int32
const (
Protocol_PROTOCOL_UNSPECIFIED Protocol = 0
Protocol_PROTOCOL_TCP Protocol = 1
Protocol_PROTOCOL_UDP Protocol = 2
)
// Enum value maps for Protocol.
var (
Protocol_name = map[int32]string{
0: "PROTOCOL_UNSPECIFIED",
1: "PROTOCOL_TCP",
2: "PROTOCOL_UDP",
}
Protocol_value = map[string]int32{
"PROTOCOL_UNSPECIFIED": 0,
"PROTOCOL_TCP": 1,
"PROTOCOL_UDP": 2,
}
)
func (x Protocol) Enum() *Protocol {
p := new(Protocol)
*p = x
return p
}
func (x Protocol) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Protocol) Descriptor() protoreflect.EnumDescriptor {
return file_example_proto_enumTypes[0].Descriptor()
}
func (Protocol) Type() protoreflect.EnumType {
return &file_example_proto_enumTypes[0]
}
func (x Protocol) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Protocol.Descriptor instead.
func (Protocol) EnumDescriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{0}
}
type Primitives struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DoubleVal float64 `protobuf:"fixed64,1,opt,name=double_val,json=doubleVal,proto3" json:"double_val,omitempty"`
FloatVal float32 `protobuf:"fixed32,2,opt,name=float_val,json=floatVal,proto3" json:"float_val,omitempty"`
Int32Val int32 `protobuf:"varint,3,opt,name=int32_val,json=int32Val,proto3" json:"int32_val,omitempty"`
Int64Val int64 `protobuf:"varint,4,opt,name=int64_val,json=int64Val,proto3" json:"int64_val,omitempty"`
Uint32Val uint32 `protobuf:"varint,5,opt,name=uint32_val,json=uint32Val,proto3" json:"uint32_val,omitempty"`
Uint64Val uint64 `protobuf:"varint,6,opt,name=uint64_val,json=uint64Val,proto3" json:"uint64_val,omitempty"`
Sint32Val int32 `protobuf:"zigzag32,7,opt,name=sint32_val,json=sint32Val,proto3" json:"sint32_val,omitempty"`
Sint64Val int64 `protobuf:"zigzag64,8,opt,name=sint64_val,json=sint64Val,proto3" json:"sint64_val,omitempty"`
Fixed32Val uint32 `protobuf:"fixed32,9,opt,name=fixed32_val,json=fixed32Val,proto3" json:"fixed32_val,omitempty"`
Fixed64Val uint64 `protobuf:"fixed64,10,opt,name=fixed64_val,json=fixed64Val,proto3" json:"fixed64_val,omitempty"`
Sfixed32Val int32 `protobuf:"fixed32,11,opt,name=sfixed32_val,json=sfixed32Val,proto3" json:"sfixed32_val,omitempty"`
Sfixed64Val int64 `protobuf:"fixed64,12,opt,name=sfixed64_val,json=sfixed64Val,proto3" json:"sfixed64_val,omitempty"`
BoolVal bool `protobuf:"varint,13,opt,name=bool_val,json=boolVal,proto3" json:"bool_val,omitempty"`
StringVal string `protobuf:"bytes,14,opt,name=string_val,json=stringVal,proto3" json:"string_val,omitempty"`
ByteVal []byte `protobuf:"bytes,15,opt,name=byte_val,json=byteVal,proto3" json:"byte_val,omitempty"`
}
func (x *Primitives) Reset() {
*x = Primitives{}
if protoimpl.UnsafeEnabled {
mi := &file_example_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Primitives) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Primitives) ProtoMessage() {}
func (x *Primitives) ProtoReflect() protoreflect.Message {
mi := &file_example_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Primitives.ProtoReflect.Descriptor instead.
func (*Primitives) Descriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{0}
}
func (x *Primitives) GetDoubleVal() float64 {
if x != nil {
return x.DoubleVal
}
return 0
}
func (x *Primitives) GetFloatVal() float32 {
if x != nil {
return x.FloatVal
}
return 0
}
func (x *Primitives) GetInt32Val() int32 {
if x != nil {
return x.Int32Val
}
return 0
}
func (x *Primitives) GetInt64Val() int64 {
if x != nil {
return x.Int64Val
}
return 0
}
func (x *Primitives) GetUint32Val() uint32 {
if x != nil {
return x.Uint32Val
}
return 0
}
func (x *Primitives) GetUint64Val() uint64 {
if x != nil {
return x.Uint64Val
}
return 0
}
func (x *Primitives) GetSint32Val() int32 {
if x != nil {
return x.Sint32Val
}
return 0
}
func (x *Primitives) GetSint64Val() int64 {
if x != nil {
return x.Sint64Val
}
return 0
}
func (x *Primitives) GetFixed32Val() uint32 {
if x != nil {
return x.Fixed32Val
}
return 0
}
func (x *Primitives) GetFixed64Val() uint64 {
if x != nil {
return x.Fixed64Val
}
return 0
}
func (x *Primitives) GetSfixed32Val() int32 {
if x != nil {
return x.Sfixed32Val
}
return 0
}
func (x *Primitives) GetSfixed64Val() int64 {
if x != nil {
return x.Sfixed64Val
}
return 0
}
func (x *Primitives) GetBoolVal() bool {
if x != nil {
return x.BoolVal
}
return false
}
func (x *Primitives) GetStringVal() string {
if x != nil {
return x.StringVal
}
return ""
}
func (x *Primitives) GetByteVal() []byte {
if x != nil {
return x.ByteVal
}
return nil
}
type NestedAndCollections struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Primitives *Primitives `protobuf:"bytes,1,opt,name=primitives,proto3" json:"primitives,omitempty"`
PrimitivesList []*Primitives `protobuf:"bytes,2,rep,name=primitives_list,json=primitivesList,proto3" json:"primitives_list,omitempty"`
PrimitivesMap map[string]*Primitives `protobuf:"bytes,3,rep,name=primitives_map,json=primitivesMap,proto3" json:"primitives_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
ProtocolMap map[string]Protocol `protobuf:"bytes,4,rep,name=protocol_map,json=protocolMap,proto3" json:"protocol_map,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3,enum=hashicorp.consul.internal.protohcl.testproto.Protocol"`
IntList []int32 `protobuf:"varint,5,rep,packed,name=int_list,json=intList,proto3" json:"int_list,omitempty"`
}
func (x *NestedAndCollections) Reset() {
*x = NestedAndCollections{}
if protoimpl.UnsafeEnabled {
mi := &file_example_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *NestedAndCollections) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NestedAndCollections) ProtoMessage() {}
func (x *NestedAndCollections) ProtoReflect() protoreflect.Message {
mi := &file_example_proto_msgTypes[1]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use NestedAndCollections.ProtoReflect.Descriptor instead.
func (*NestedAndCollections) Descriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{1}
}
func (x *NestedAndCollections) GetPrimitives() *Primitives {
if x != nil {
return x.Primitives
}
return nil
}
func (x *NestedAndCollections) GetPrimitivesList() []*Primitives {
if x != nil {
return x.PrimitivesList
}
return nil
}
func (x *NestedAndCollections) GetPrimitivesMap() map[string]*Primitives {
if x != nil {
return x.PrimitivesMap
}
return nil
}
func (x *NestedAndCollections) GetProtocolMap() map[string]Protocol {
if x != nil {
return x.ProtocolMap
}
return nil
}
func (x *NestedAndCollections) GetIntList() []int32 {
if x != nil {
return x.IntList
}
return nil
}
type Wrappers struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
DoubleVal *wrapperspb.DoubleValue `protobuf:"bytes,1,opt,name=double_val,json=doubleVal,proto3" json:"double_val,omitempty"`
FloatVal *wrapperspb.FloatValue `protobuf:"bytes,2,opt,name=float_val,json=floatVal,proto3" json:"float_val,omitempty"`
Int32Val *wrapperspb.Int32Value `protobuf:"bytes,3,opt,name=int32_val,json=int32Val,proto3" json:"int32_val,omitempty"`
Int64Val *wrapperspb.Int64Value `protobuf:"bytes,4,opt,name=int64_val,json=int64Val,proto3" json:"int64_val,omitempty"`
Uint32Val *wrapperspb.UInt32Value `protobuf:"bytes,5,opt,name=uint32_val,json=uint32Val,proto3" json:"uint32_val,omitempty"`
Uint64Val *wrapperspb.UInt64Value `protobuf:"bytes,6,opt,name=uint64_val,json=uint64Val,proto3" json:"uint64_val,omitempty"`
BoolVal *wrapperspb.BoolValue `protobuf:"bytes,13,opt,name=bool_val,json=boolVal,proto3" json:"bool_val,omitempty"`
StringVal *wrapperspb.StringValue `protobuf:"bytes,14,opt,name=string_val,json=stringVal,proto3" json:"string_val,omitempty"`
BytesVal *wrapperspb.BytesValue `protobuf:"bytes,15,opt,name=bytes_val,json=bytesVal,proto3" json:"bytes_val,omitempty"`
}
func (x *Wrappers) Reset() {
*x = Wrappers{}
if protoimpl.UnsafeEnabled {
mi := &file_example_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *Wrappers) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Wrappers) ProtoMessage() {}
func (x *Wrappers) ProtoReflect() protoreflect.Message {
mi := &file_example_proto_msgTypes[2]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Wrappers.ProtoReflect.Descriptor instead.
func (*Wrappers) Descriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{2}
}
func (x *Wrappers) GetDoubleVal() *wrapperspb.DoubleValue {
if x != nil {
return x.DoubleVal
}
return nil
}
func (x *Wrappers) GetFloatVal() *wrapperspb.FloatValue {
if x != nil {
return x.FloatVal
}
return nil
}
func (x *Wrappers) GetInt32Val() *wrapperspb.Int32Value {
if x != nil {
return x.Int32Val
}
return nil
}
func (x *Wrappers) GetInt64Val() *wrapperspb.Int64Value {
if x != nil {
return x.Int64Val
}
return nil
}
func (x *Wrappers) GetUint32Val() *wrapperspb.UInt32Value {
if x != nil {
return x.Uint32Val
}
return nil
}
func (x *Wrappers) GetUint64Val() *wrapperspb.UInt64Value {
if x != nil {
return x.Uint64Val
}
return nil
}
func (x *Wrappers) GetBoolVal() *wrapperspb.BoolValue {
if x != nil {
return x.BoolVal
}
return nil
}
func (x *Wrappers) GetStringVal() *wrapperspb.StringValue {
if x != nil {
return x.StringVal
}
return nil
}
func (x *Wrappers) GetBytesVal() *wrapperspb.BytesValue {
if x != nil {
return x.BytesVal
}
return nil
}
type OneOf struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Types that are assignable to Data:
//
// *OneOf_Int32Val
// *OneOf_Primitives
Data isOneOf_Data `protobuf_oneof:"data"`
}
func (x *OneOf) Reset() {
*x = OneOf{}
if protoimpl.UnsafeEnabled {
mi := &file_example_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *OneOf) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*OneOf) ProtoMessage() {}
func (x *OneOf) ProtoReflect() protoreflect.Message {
mi := &file_example_proto_msgTypes[3]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use OneOf.ProtoReflect.Descriptor instead.
func (*OneOf) Descriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{3}
}
func (m *OneOf) GetData() isOneOf_Data {
if m != nil {
return m.Data
}
return nil
}
func (x *OneOf) GetInt32Val() int32 {
if x, ok := x.GetData().(*OneOf_Int32Val); ok {
return x.Int32Val
}
return 0
}
func (x *OneOf) GetPrimitives() *Primitives {
if x, ok := x.GetData().(*OneOf_Primitives); ok {
return x.Primitives
}
return nil
}
type isOneOf_Data interface {
isOneOf_Data()
}
type OneOf_Int32Val struct {
Int32Val int32 `protobuf:"varint,1,opt,name=int32_val,json=int32Val,proto3,oneof"`
}
type OneOf_Primitives struct {
Primitives *Primitives `protobuf:"bytes,2,opt,name=primitives,proto3,oneof"` // note repeated fields (including maps) are not allowed in oneofs
}
func (*OneOf_Int32Val) isOneOf_Data() {}
func (*OneOf_Primitives) isOneOf_Data() {}
type NonDynamicWellKnown struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
EmptyVal *emptypb.Empty `protobuf:"bytes,1,opt,name=empty_val,json=emptyVal,proto3" json:"empty_val,omitempty"`
TimestampVal *timestamppb.Timestamp `protobuf:"bytes,2,opt,name=timestamp_val,json=timestampVal,proto3" json:"timestamp_val,omitempty"`
DurationVal *durationpb.Duration `protobuf:"bytes,3,opt,name=duration_val,json=durationVal,proto3" json:"duration_val,omitempty"`
}
func (x *NonDynamicWellKnown) Reset() {
*x = NonDynamicWellKnown{}
if protoimpl.UnsafeEnabled {
mi := &file_example_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *NonDynamicWellKnown) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*NonDynamicWellKnown) ProtoMessage() {}
func (x *NonDynamicWellKnown) ProtoReflect() protoreflect.Message {
mi := &file_example_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use NonDynamicWellKnown.ProtoReflect.Descriptor instead.
func (*NonDynamicWellKnown) Descriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{4}
}
func (x *NonDynamicWellKnown) GetEmptyVal() *emptypb.Empty {
if x != nil {
return x.EmptyVal
}
return nil
}
func (x *NonDynamicWellKnown) GetTimestampVal() *timestamppb.Timestamp {
if x != nil {
return x.TimestampVal
}
return nil
}
func (x *NonDynamicWellKnown) GetDurationVal() *durationpb.Duration {
if x != nil {
return x.DurationVal
}
return nil
}
type DynamicWellKnown struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
AnyVal *anypb.Any `protobuf:"bytes,1,opt,name=any_val,json=anyVal,proto3" json:"any_val,omitempty"`
StructVal *structpb.Struct `protobuf:"bytes,2,opt,name=struct_val,json=structVal,proto3" json:"struct_val,omitempty"`
AnyList []*anypb.Any `protobuf:"bytes,3,rep,name=any_list,json=anyList,proto3" json:"any_list,omitempty"`
}
func (x *DynamicWellKnown) Reset() {
*x = DynamicWellKnown{}
if protoimpl.UnsafeEnabled {
mi := &file_example_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DynamicWellKnown) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DynamicWellKnown) ProtoMessage() {}
func (x *DynamicWellKnown) ProtoReflect() protoreflect.Message {
mi := &file_example_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DynamicWellKnown.ProtoReflect.Descriptor instead.
func (*DynamicWellKnown) Descriptor() ([]byte, []int) {
return file_example_proto_rawDescGZIP(), []int{5}
}
func (x *DynamicWellKnown) GetAnyVal() *anypb.Any {
if x != nil {
return x.AnyVal
}
return nil
}
func (x *DynamicWellKnown) GetStructVal() *structpb.Struct {
if x != nil {
return x.StructVal
}
return nil
}
func (x *DynamicWellKnown) GetAnyList() []*anypb.Any {
if x != nil {
return x.AnyList
}
return nil
}
var File_example_proto protoreflect.FileDescriptor
var file_example_proto_rawDesc = []byte{
0x0a, 0x0d, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12,
0x2c, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x64,
0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1b, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x65,
0x6d, 0x70, 0x74, 0x79, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x77, 0x72, 0x61,
0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x19, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x61, 0x6e, 0x79,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1c, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x22, 0xdb, 0x03, 0x0a, 0x0a, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69,
0x76, 0x65, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61,
0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x64, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56,
0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18,
0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61, 0x6c, 0x12,
0x1b, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01,
0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1b, 0x0a, 0x09,
0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52,
0x08, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x69, 0x6e,
0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x09, 0x75,
0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74,
0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x04, 0x52, 0x09, 0x75, 0x69,
0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x6e, 0x74, 0x33,
0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x11, 0x52, 0x09, 0x73, 0x69, 0x6e,
0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x69, 0x6e, 0x74, 0x36, 0x34,
0x5f, 0x76, 0x61, 0x6c, 0x18, 0x08, 0x20, 0x01, 0x28, 0x12, 0x52, 0x09, 0x73, 0x69, 0x6e, 0x74,
0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32,
0x5f, 0x76, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x07, 0x52, 0x0a, 0x66, 0x69, 0x78, 0x65,
0x64, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36,
0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x06, 0x52, 0x0a, 0x66, 0x69, 0x78,
0x65, 0x64, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x66, 0x69, 0x78, 0x65,
0x64, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0f, 0x52, 0x0b, 0x73,
0x66, 0x69, 0x78, 0x65, 0x64, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x73, 0x66,
0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x10,
0x52, 0x0b, 0x73, 0x66, 0x69, 0x78, 0x65, 0x64, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x19, 0x0a,
0x08, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x08, 0x52,
0x07, 0x62, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x69,
0x6e, 0x67, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x74,
0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x79, 0x74, 0x65, 0x5f,
0x76, 0x61, 0x6c, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x62, 0x79, 0x74, 0x65, 0x56,
0x61, 0x6c, 0x22, 0xd8, 0x05, 0x0a, 0x14, 0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x6e, 0x64,
0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x58, 0x0a, 0x0a, 0x70,
0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73,
0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50,
0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x69,
0x74, 0x69, 0x76, 0x65, 0x73, 0x12, 0x61, 0x0a, 0x0f, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69,
0x76, 0x65, 0x73, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x38,
0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75,
0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72,
0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x52, 0x0e, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74,
0x69, 0x76, 0x65, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x7c, 0x0a, 0x0e, 0x70, 0x72, 0x69, 0x6d,
0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b,
0x32, 0x55, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x4e, 0x65, 0x73, 0x74, 0x65, 0x64, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74,
0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x4d,
0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x0d, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69,
0x76, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x12, 0x76, 0x0a, 0x0c, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63,
0x6f, 0x6c, 0x5f, 0x6d, 0x61, 0x70, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x53, 0x2e, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63,
0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x4e, 0x65, 0x73, 0x74,
0x65, 0x64, 0x41, 0x6e, 0x64, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73,
0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72,
0x79, 0x52, 0x0b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x4d, 0x61, 0x70, 0x12, 0x19,
0x0a, 0x08, 0x69, 0x6e, 0x74, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x05, 0x20, 0x03, 0x28, 0x05,
0x52, 0x07, 0x69, 0x6e, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x1a, 0x7a, 0x0a, 0x12, 0x50, 0x72, 0x69,
0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12,
0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65,
0x79, 0x12, 0x4e, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x38, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e,
0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e,
0x50, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75,
0x65, 0x3a, 0x02, 0x38, 0x01, 0x1a, 0x76, 0x0a, 0x10, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f,
0x6c, 0x4d, 0x61, 0x70, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x6b, 0x65, 0x79,
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x6b, 0x65, 0x79, 0x12, 0x4c, 0x0a, 0x05, 0x76,
0x61, 0x6c, 0x75, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x36, 0x2e, 0x68, 0x61, 0x73,
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e,
0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63,
0x6f, 0x6c, 0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x9d, 0x04,
0x0a, 0x08, 0x57, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x12, 0x3b, 0x0a, 0x0a, 0x64, 0x6f,
0x75, 0x62, 0x6c, 0x65, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x44, 0x6f, 0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x64, 0x6f,
0x75, 0x62, 0x6c, 0x65, 0x56, 0x61, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x66, 0x6c, 0x6f, 0x61, 0x74,
0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x6c, 0x6f,
0x61, 0x74, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x66, 0x6c, 0x6f, 0x61, 0x74, 0x56, 0x61,
0x6c, 0x12, 0x38, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75,
0x65, 0x52, 0x08, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x69,
0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x08, 0x69, 0x6e, 0x74,
0x36, 0x34, 0x56, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x5f,
0x76, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74,
0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x33, 0x32, 0x56,
0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0a, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x5f, 0x76, 0x61, 0x6c,
0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x55, 0x49, 0x6e, 0x74, 0x36, 0x34, 0x56,
0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x75, 0x69, 0x6e, 0x74, 0x36, 0x34, 0x56, 0x61, 0x6c, 0x12,
0x35, 0x0a, 0x08, 0x62, 0x6f, 0x6f, 0x6c, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0d, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x07, 0x62,
0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x12, 0x3b, 0x0a, 0x0a, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x5f, 0x76, 0x61, 0x6c, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1c, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72,
0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x52, 0x09, 0x73, 0x74, 0x72, 0x69, 0x6e, 0x67,
0x56, 0x61, 0x6c, 0x12, 0x38, 0x0a, 0x09, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x76, 0x61, 0x6c,
0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61,
0x6c, 0x75, 0x65, 0x52, 0x08, 0x62, 0x79, 0x74, 0x65, 0x73, 0x56, 0x61, 0x6c, 0x22, 0x8a, 0x01,
0x0a, 0x05, 0x4f, 0x6e, 0x65, 0x4f, 0x66, 0x12, 0x1d, 0x0a, 0x09, 0x69, 0x6e, 0x74, 0x33, 0x32,
0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x48, 0x00, 0x52, 0x08, 0x69, 0x6e,
0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x12, 0x5a, 0x0a, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74,
0x69, 0x76, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x38, 0x2e, 0x68, 0x61, 0x73,
0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e,
0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e,
0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2e, 0x50, 0x72, 0x69, 0x6d, 0x69, 0x74,
0x69, 0x76, 0x65, 0x73, 0x48, 0x00, 0x52, 0x0a, 0x70, 0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76,
0x65, 0x73, 0x42, 0x06, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x22, 0xc9, 0x01, 0x0a, 0x13, 0x4e,
0x6f, 0x6e, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f,
0x77, 0x6e, 0x12, 0x33, 0x0a, 0x09, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x52, 0x08, 0x65,
0x6d, 0x70, 0x74, 0x79, 0x56, 0x61, 0x6c, 0x12, 0x3f, 0x0a, 0x0d, 0x74, 0x69, 0x6d, 0x65, 0x73,
0x74, 0x61, 0x6d, 0x70, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x74, 0x69, 0x6d, 0x65,
0x73, 0x74, 0x61, 0x6d, 0x70, 0x56, 0x61, 0x6c, 0x12, 0x3c, 0x0a, 0x0c, 0x64, 0x75, 0x72, 0x61,
0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x75, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x56, 0x61, 0x6c, 0x22, 0xaa, 0x01, 0x0a, 0x10, 0x44, 0x79, 0x6e, 0x61, 0x6d,
0x69, 0x63, 0x57, 0x65, 0x6c, 0x6c, 0x4b, 0x6e, 0x6f, 0x77, 0x6e, 0x12, 0x2d, 0x0a, 0x07, 0x61,
0x6e, 0x79, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41,
0x6e, 0x79, 0x52, 0x06, 0x61, 0x6e, 0x79, 0x56, 0x61, 0x6c, 0x12, 0x36, 0x0a, 0x0a, 0x73, 0x74,
0x72, 0x75, 0x63, 0x74, 0x5f, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x09, 0x73, 0x74, 0x72, 0x75, 0x63, 0x74, 0x56,
0x61, 0x6c, 0x12, 0x2f, 0x0a, 0x08, 0x61, 0x6e, 0x79, 0x5f, 0x6c, 0x69, 0x73, 0x74, 0x18, 0x03,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x41, 0x6e, 0x79, 0x52, 0x07, 0x61, 0x6e, 0x79, 0x4c,
0x69, 0x73, 0x74, 0x2a, 0x48, 0x0a, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12,
0x18, 0x0a, 0x14, 0x50, 0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x55, 0x4e, 0x53, 0x50,
0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x10, 0x0a, 0x0c, 0x50, 0x52, 0x4f,
0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x54, 0x43, 0x50, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x50,
0x52, 0x4f, 0x54, 0x4f, 0x43, 0x4f, 0x4c, 0x5f, 0x55, 0x44, 0x50, 0x10, 0x02, 0x42, 0xcf, 0x02,
0x0a, 0x30, 0x63, 0x6f, 0x6d, 0x2e, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x42, 0x0c, 0x45, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f,
0x50, 0x01, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2f,
0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63,
0x6c, 0x2f, 0x74, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0xa2, 0x02, 0x05, 0x48, 0x43,
0x49, 0x50, 0x54, 0xaa, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2e,
0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x2e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2e,
0x50, 0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0xca, 0x02, 0x2c, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43,
0x6f, 0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50,
0x72, 0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0xe2, 0x02, 0x38, 0x48, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x5c, 0x43, 0x6f,
0x6e, 0x73, 0x75, 0x6c, 0x5c, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5c, 0x50, 0x72,
0x6f, 0x74, 0x6f, 0x68, 0x63, 0x6c, 0x5c, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x5c, 0x47, 0x50, 0x42, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0xea, 0x02, 0x30, 0x48,
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x3a, 0x3a, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6c,
0x3a, 0x3a, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x3a, 0x3a, 0x50, 0x72, 0x6f, 0x74,
0x6f, 0x68, 0x63, 0x6c, 0x3a, 0x3a, 0x54, 0x65, 0x73, 0x74, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_example_proto_rawDescOnce sync.Once
file_example_proto_rawDescData = file_example_proto_rawDesc
)
func file_example_proto_rawDescGZIP() []byte {
file_example_proto_rawDescOnce.Do(func() {
file_example_proto_rawDescData = protoimpl.X.CompressGZIP(file_example_proto_rawDescData)
})
return file_example_proto_rawDescData
}
var file_example_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
var file_example_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_example_proto_goTypes = []interface{}{
(Protocol)(0), // 0: hashicorp.consul.internal.protohcl.testproto.Protocol
(*Primitives)(nil), // 1: hashicorp.consul.internal.protohcl.testproto.Primitives
(*NestedAndCollections)(nil), // 2: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections
(*Wrappers)(nil), // 3: hashicorp.consul.internal.protohcl.testproto.Wrappers
(*OneOf)(nil), // 4: hashicorp.consul.internal.protohcl.testproto.OneOf
(*NonDynamicWellKnown)(nil), // 5: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown
(*DynamicWellKnown)(nil), // 6: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown
nil, // 7: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.PrimitivesMapEntry
nil, // 8: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.ProtocolMapEntry
(*wrapperspb.DoubleValue)(nil), // 9: google.protobuf.DoubleValue
(*wrapperspb.FloatValue)(nil), // 10: google.protobuf.FloatValue
(*wrapperspb.Int32Value)(nil), // 11: google.protobuf.Int32Value
(*wrapperspb.Int64Value)(nil), // 12: google.protobuf.Int64Value
(*wrapperspb.UInt32Value)(nil), // 13: google.protobuf.UInt32Value
(*wrapperspb.UInt64Value)(nil), // 14: google.protobuf.UInt64Value
(*wrapperspb.BoolValue)(nil), // 15: google.protobuf.BoolValue
(*wrapperspb.StringValue)(nil), // 16: google.protobuf.StringValue
(*wrapperspb.BytesValue)(nil), // 17: google.protobuf.BytesValue
(*emptypb.Empty)(nil), // 18: google.protobuf.Empty
(*timestamppb.Timestamp)(nil), // 19: google.protobuf.Timestamp
(*durationpb.Duration)(nil), // 20: google.protobuf.Duration
(*anypb.Any)(nil), // 21: google.protobuf.Any
(*structpb.Struct)(nil), // 22: google.protobuf.Struct
}
var file_example_proto_depIdxs = []int32{
1, // 0: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.primitives:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives
1, // 1: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.primitives_list:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives
7, // 2: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.primitives_map:type_name -> hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.PrimitivesMapEntry
8, // 3: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.protocol_map:type_name -> hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.ProtocolMapEntry
9, // 4: hashicorp.consul.internal.protohcl.testproto.Wrappers.double_val:type_name -> google.protobuf.DoubleValue
10, // 5: hashicorp.consul.internal.protohcl.testproto.Wrappers.float_val:type_name -> google.protobuf.FloatValue
11, // 6: hashicorp.consul.internal.protohcl.testproto.Wrappers.int32_val:type_name -> google.protobuf.Int32Value
12, // 7: hashicorp.consul.internal.protohcl.testproto.Wrappers.int64_val:type_name -> google.protobuf.Int64Value
13, // 8: hashicorp.consul.internal.protohcl.testproto.Wrappers.uint32_val:type_name -> google.protobuf.UInt32Value
14, // 9: hashicorp.consul.internal.protohcl.testproto.Wrappers.uint64_val:type_name -> google.protobuf.UInt64Value
15, // 10: hashicorp.consul.internal.protohcl.testproto.Wrappers.bool_val:type_name -> google.protobuf.BoolValue
16, // 11: hashicorp.consul.internal.protohcl.testproto.Wrappers.string_val:type_name -> google.protobuf.StringValue
17, // 12: hashicorp.consul.internal.protohcl.testproto.Wrappers.bytes_val:type_name -> google.protobuf.BytesValue
1, // 13: hashicorp.consul.internal.protohcl.testproto.OneOf.primitives:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives
18, // 14: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown.empty_val:type_name -> google.protobuf.Empty
19, // 15: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown.timestamp_val:type_name -> google.protobuf.Timestamp
20, // 16: hashicorp.consul.internal.protohcl.testproto.NonDynamicWellKnown.duration_val:type_name -> google.protobuf.Duration
21, // 17: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown.any_val:type_name -> google.protobuf.Any
22, // 18: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown.struct_val:type_name -> google.protobuf.Struct
21, // 19: hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown.any_list:type_name -> google.protobuf.Any
1, // 20: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.PrimitivesMapEntry.value:type_name -> hashicorp.consul.internal.protohcl.testproto.Primitives
0, // 21: hashicorp.consul.internal.protohcl.testproto.NestedAndCollections.ProtocolMapEntry.value:type_name -> hashicorp.consul.internal.protohcl.testproto.Protocol
22, // [22:22] is the sub-list for method output_type
22, // [22:22] is the sub-list for method input_type
22, // [22:22] is the sub-list for extension type_name
22, // [22:22] is the sub-list for extension extendee
0, // [0:22] is the sub-list for field type_name
}
func init() { file_example_proto_init() }
func file_example_proto_init() {
if File_example_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_example_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Primitives); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_example_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NestedAndCollections); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_example_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Wrappers); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_example_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*OneOf); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_example_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*NonDynamicWellKnown); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_example_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DynamicWellKnown); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_example_proto_msgTypes[3].OneofWrappers = []interface{}{
(*OneOf_Int32Val)(nil),
(*OneOf_Primitives)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_example_proto_rawDesc,
NumEnums: 1,
NumMessages: 8,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_example_proto_goTypes,
DependencyIndexes: file_example_proto_depIdxs,
EnumInfos: file_example_proto_enumTypes,
MessageInfos: file_example_proto_msgTypes,
}.Build()
File_example_proto = out.File
file_example_proto_rawDesc = nil
file_example_proto_goTypes = nil
file_example_proto_depIdxs = nil
}

View File

@ -0,0 +1,74 @@
syntax = "proto3";
package hashicorp.consul.internal.protohcl.testproto;
import "google/protobuf/duration.proto";
import "google/protobuf/empty.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/wrappers.proto";
import "google/protobuf/any.proto";
import "google/protobuf/struct.proto";
message Primitives {
double double_val = 1;
float float_val = 2;
int32 int32_val = 3;
int64 int64_val = 4;
uint32 uint32_val = 5;
uint64 uint64_val = 6;
sint32 sint32_val = 7;
sint64 sint64_val = 8;
fixed32 fixed32_val = 9;
fixed64 fixed64_val = 10;
sfixed32 sfixed32_val = 11;
sfixed64 sfixed64_val = 12;
bool bool_val = 13;
string string_val = 14;
bytes byte_val = 15;
}
enum Protocol {
PROTOCOL_UNSPECIFIED = 0;
PROTOCOL_TCP = 1;
PROTOCOL_UDP = 2;
}
message NestedAndCollections {
Primitives primitives = 1;
repeated Primitives primitives_list = 2;
map<string, Primitives> primitives_map = 3;
map<string, Protocol> protocol_map = 4;
repeated int32 int_list = 5;
}
message Wrappers {
google.protobuf.DoubleValue double_val = 1;
google.protobuf.FloatValue float_val = 2;
google.protobuf.Int32Value int32_val = 3;
google.protobuf.Int64Value int64_val = 4;
google.protobuf.UInt32Value uint32_val = 5;
google.protobuf.UInt64Value uint64_val = 6;
google.protobuf.BoolValue bool_val = 13;
google.protobuf.StringValue string_val = 14;
google.protobuf.BytesValue bytes_val = 15;
}
message OneOf {
oneof data {
int32 int32_val = 1;
Primitives primitives = 2;
// note repeated fields (including maps) are not allowed in oneofs
}
}
message NonDynamicWellKnown {
google.protobuf.Empty empty_val = 1;
google.protobuf.Timestamp timestamp_val = 2;
google.protobuf.Duration duration_val = 3;
}
message DynamicWellKnown {
google.protobuf.Any any_val = 1;
google.protobuf.Struct struct_val = 2;
repeated google.protobuf.Any any_list = 3;
}

View File

@ -0,0 +1,134 @@
package protohcl
import (
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/hclparse"
"github.com/zclconf/go-cty/cty/function"
"google.golang.org/protobuf/reflect/protoreflect"
)
// UnmarshalContext provides information about the context in which we are
// unmarshalling HCL. It is primarily used for decoding Any fields based on
// surrounding information (e.g. the resource Type block).
type UnmarshalContext struct {
// Parent context.
Parent *UnmarshalContext
// Name of the field that we are unmarshalling.
Name string
// Message is the protobuf message that we are unmarshalling into (may be nil).
Message protoreflect.Message
// Range of where this field was in the HCL source.
Range hcl.Range
}
// ErrorRange returns a range that can be used in error messages.
func (ctx *UnmarshalContext) ErrorRange() hcl.Range {
for {
if !ctx.Range.Empty() || ctx.Parent == nil {
return ctx.Range
}
ctx = ctx.Parent
}
}
func Unmarshal(src []byte, dest protoreflect.ProtoMessage) error {
return UnmarshalOptions{}.Unmarshal(src, dest)
}
type UnmarshalOptions struct {
AnyTypeProvider AnyTypeProvider
SourceFileName string
FieldNamer FieldNamer
Functions map[string]function.Function
}
func (u UnmarshalOptions) Unmarshal(src []byte, dest protoreflect.ProtoMessage) error {
rmsg := dest.ProtoReflect()
file, diags := hclparse.NewParser().ParseHCL(src, u.SourceFileName)
// error performing basic HCL parsing
if diags.HasErrors() {
return diags
}
u.clearAll(rmsg)
if u.FieldNamer == nil {
u.FieldNamer = textFieldNamer{}
}
return u.decodeMessage(
&UnmarshalContext{Message: rmsg},
u.bodyDecoder(file.Body),
rmsg,
)
}
func (u UnmarshalOptions) bodyDecoder(body hcl.Body) MessageDecoder {
return newBodyDecoder(body, u.FieldNamer, u.Functions)
}
func (u UnmarshalOptions) decodeMessage(ctx *UnmarshalContext, decoder MessageDecoder, msg protoreflect.Message) error {
desc := msg.Descriptor()
if desc.FullName() == wellKnownTypeAny {
return u.decodeAny(ctx, decoder, msg)
}
tracker := newOneOfTracker(u.FieldNamer)
return decoder.EachField(FieldIterator{
Desc: desc,
Func: func(field *IterField) error {
if err := tracker.markFieldAsSet(field.Desc); err != nil {
return err
}
var (
protoVal protoreflect.Value
err error
)
switch {
case field.Val != nil:
protoVal, err = u.decodeAttribute(
&UnmarshalContext{
Parent: ctx,
Name: field.Name,
Range: field.Range,
},
func() protoreflect.Value { return msg.NewField(field.Desc) },
field.Desc,
*field.Val,
true,
)
case len(field.Blocks) != 0:
protoVal, err = u.decodeBlocks(ctx, field.Blocks, msg, field.Desc)
default:
panic("decoder yielded no blocks or attributes")
}
if err != nil {
return err
}
if protoVal.IsValid() {
msg.Set(field.Desc, protoVal)
}
return nil
},
})
}
type newMessageFn func() protoreflect.Value
func (u UnmarshalOptions) clearAll(msg protoreflect.Message) {
fields := msg.Descriptor().Fields()
for i := 0; i < fields.Len(); i++ {
msg.Clear(fields.Get(i))
}
}

View File

@ -0,0 +1,557 @@
package protohcl
import (
"encoding/json"
"fmt"
"reflect"
"testing"
"time"
"github.com/stretchr/testify/require"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/types/known/anypb"
"github.com/hashicorp/consul/internal/protohcl/testproto"
"github.com/hashicorp/hcl/v2/hclparse"
)
func TestPrimitives(t *testing.T) {
hcl := `
double_val = 1.234
float_val = 2.345
int32_val = 536870912
int64_val = 25769803776
uint32_val = 2148532224
uint64_val = 9223372041149743104
sint32_val = 536870912
sint64_val = 25769803776
fixed32_val = 2148532224
fixed64_val = 9223372041149743104
sfixed32_val = 536870912
sfixed64_val = 25769803776
bool_val = true
string_val = "foo"
// This is base64 encoded "bar"
byte_val = "YmFy"
`
var out testproto.Primitives
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.Equal(t, out.DoubleVal, float64(1.234))
require.Equal(t, out.FloatVal, float32(2.345))
require.Equal(t, out.Int32Val, int32(536870912))
require.Equal(t, out.Int64Val, int64(25769803776))
require.Equal(t, out.Uint32Val, uint32(2148532224))
require.Equal(t, out.Uint64Val, uint64(9223372041149743104))
require.Equal(t, out.Sint32Val, int32(536870912))
require.Equal(t, out.Sint64Val, int64(25769803776))
require.Equal(t, out.Fixed32Val, uint32(2148532224))
require.Equal(t, out.Fixed64Val, uint64(9223372041149743104))
require.Equal(t, out.Sfixed32Val, int32(536870912))
require.Equal(t, out.Sfixed64Val, int64(25769803776))
require.Equal(t, out.BoolVal, true)
require.Equal(t, out.StringVal, "foo")
require.Equal(t, out.ByteVal, []byte("bar"))
}
func TestNestedAndCollections(t *testing.T) {
hcl := `
primitives {
uint32_val = 42
}
primitives_map "foo" {
uint32_val = 42
}
protocol_map = {
"foo" = "PROTOCOL_TCP"
}
primitives_list {
uint32_val = 42
}
primitives_list {
uint32_val = 56
}
int_list = [
1,
2
]
`
var out testproto.NestedAndCollections
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.Primitives)
require.Equal(t, out.Primitives.Uint32Val, uint32(42))
require.NotNil(t, out.PrimitivesMap)
require.Equal(t, out.PrimitivesMap["foo"].Uint32Val, uint32(42))
require.NotNil(t, out.ProtocolMap)
require.Equal(t, out.ProtocolMap["foo"], testproto.Protocol_PROTOCOL_TCP)
require.Len(t, out.PrimitivesList, 2)
require.Equal(t, out.PrimitivesList[0].Uint32Val, uint32(42))
require.Equal(t, out.PrimitivesList[1].Uint32Val, uint32(56))
require.Len(t, out.IntList, 2)
require.Equal(t, out.IntList[1], int32(2))
}
func TestPrimitiveWrappers(t *testing.T) {
hcl := `
double_val = 1.234
float_val = 2.345
int32_val = 536870912
int64_val = 25769803776
uint32_val = 2148532224
uint64_val = 9223372041149743104
bool_val = true
string_val = "foo"
// This is base64 encoded "bar"
bytes_val = "YmFy"
`
var out testproto.Wrappers
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.Equal(t, out.DoubleVal.Value, float64(1.234))
require.Equal(t, out.FloatVal.Value, float32(2.345))
require.Equal(t, out.Int32Val.Value, int32(536870912))
require.Equal(t, out.Int64Val.Value, int64(25769803776))
require.Equal(t, out.Uint32Val.Value, uint32(2148532224))
require.Equal(t, out.Uint64Val.Value, uint64(9223372041149743104))
require.Equal(t, out.BoolVal.Value, true)
require.Equal(t, out.StringVal.Value, "foo")
require.Equal(t, out.BytesVal.Value, []byte("bar"))
}
func TestNonDynamicWellKnown(t *testing.T) {
hcl := `
empty_val = {}
timestamp_val = "2023-02-27T12:34:56.789Z"
duration_val = "12s"
`
var out testproto.NonDynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.EmptyVal)
require.NotNil(t, out.TimestampVal)
require.Equal(t, out.TimestampVal.AsTime(), time.Date(2023, 2, 27, 12, 34, 56, 789000000, time.UTC))
require.NotNil(t, out.DurationVal)
require.Equal(t, out.DurationVal.AsDuration(), time.Second*12)
}
func TestInvalidTimestamp(t *testing.T) {
if testing.Short() {
t.Skip("too slow for testing.Short")
}
t.Parallel()
cases := map[string]struct {
hcl string
expectXDS bool
}{
"invalid": {
hcl: `
timestamp_val = "Sat Jun 12 2023 14:59:57 GMT+0200"
`,
},
"range error": {
hcl: `
timestamp_val = "2023-02-27T25:34:56.789Z"
`,
},
}
for name, tc := range cases {
tc := tc
var out testproto.NonDynamicWellKnown
t.Run(name, func(t *testing.T) {
err := Unmarshal([]byte(tc.hcl), &out)
require.Error(t, err)
require.Nil(t, out.TimestampVal)
require.ErrorContains(t, err, "error parsing timestamp")
})
}
}
func TestInvalidDuration(t *testing.T) {
hcl := `
duration_val = "abc"
`
var out testproto.NonDynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.ErrorContains(t, err, "error parsing string duration:")
require.Nil(t, out.DurationVal)
}
func TestOneOf(t *testing.T) {
hcl1 := `
int32_val = 3
`
hcl2 := `
primitives {
int32_val = 3
}
`
hcl3 := `
int32_val = 3
primitives {
int32_val = 4
}
`
var out testproto.OneOf
err := Unmarshal([]byte(hcl1), &out)
require.NoError(t, err)
require.Equal(t, out.GetInt32Val(), int32(3))
err = Unmarshal([]byte(hcl2), &out)
require.NoError(t, err)
primitives := out.GetPrimitives()
require.NotNil(t, primitives)
require.Equal(t, primitives.Int32Val, int32(3))
err = Unmarshal([]byte(hcl3), &out)
require.Error(t, err)
}
func TestAny(t *testing.T) {
hcl := `
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives"
uint32_val = 42
}
any_list = [
{
type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives"
uint32_val = 123
},
{
type_url = "hashicorp.consul.internal.protohcl.testproto.Wrappers"
uint32_val = 321
}
]
`
var out testproto.DynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.AnyVal)
require.Equal(t, out.AnyVal.TypeUrl, "hashicorp.consul.internal.protohcl.testproto.Primitives")
raw, err := anypb.UnmarshalNew(out.AnyVal, proto.UnmarshalOptions{})
require.NoError(t, err)
require.NotNil(t, raw)
primitives, ok := raw.(*testproto.Primitives)
require.True(t, ok)
require.Equal(t, primitives.Uint32Val, uint32(42))
}
func TestAnyTypeDynamicWellKnown(t *testing.T) {
hcl := `
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown"
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives"
uint32_val = 42
}
}
`
var out testproto.DynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.AnyVal)
require.Equal(t, out.AnyVal.TypeUrl, "hashicorp.consul.internal.protohcl.testproto.DynamicWellKnown")
raw, err := anypb.UnmarshalNew(out.AnyVal, proto.UnmarshalOptions{})
require.NoError(t, err)
require.NotNil(t, raw)
anyVal, ok := raw.(*testproto.DynamicWellKnown)
require.True(t, ok)
res, err := anypb.UnmarshalNew(anyVal.AnyVal, proto.UnmarshalOptions{})
require.NoError(t, err)
require.NotNil(t, res)
primitives, ok := res.(*testproto.Primitives)
require.True(t, ok)
require.Equal(t, primitives.Uint32Val, uint32(42))
}
func TestAnyTypeNestedAndCollections(t *testing.T) {
hcl := `
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.NestedAndCollections"
primitives {
uint32_val = 42
}
}
`
var out testproto.DynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.AnyVal)
require.Equal(t, out.AnyVal.TypeUrl, "hashicorp.consul.internal.protohcl.testproto.NestedAndCollections")
raw, err := anypb.UnmarshalNew(out.AnyVal, proto.UnmarshalOptions{})
require.NoError(t, err)
require.NotNil(t, raw)
nestedCollections, ok := raw.(*testproto.NestedAndCollections)
require.True(t, ok)
require.NotNil(t, nestedCollections.Primitives)
require.Equal(t, nestedCollections.Primitives.Uint32Val, uint32(42))
}
func TestAnyTypeErrors(t *testing.T) {
type testCase struct {
description string
hcl string
error string
}
testCases := []testCase{
{
description: "type_url is expected",
hcl: `
any_val {
uint32_val = 42
}
`,
error: "type_url field is required to decode Any",
},
{
description: "type_url is unknown",
hcl: `
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.Integer"
uint32_val = 42
}
`,
error: "error looking up type information for hashicorp.consul.internal.protohcl.testproto.Integer",
},
{
description: "unknown field",
hcl: `
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives"
int_val = 42
}
`,
error: "Unsupported argument; An argument named \"int_val\" is not expected here",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.description, func(t *testing.T) {
t.Parallel()
var out testproto.DynamicWellKnown
err := Unmarshal([]byte(tc.hcl), &out)
require.Error(t, err)
require.Contains(t, err.Error(), tc.error)
})
}
}
func TestStruct(t *testing.T) {
hcl := `
struct_val = {
"null"= null
"bool"= true
"foo" = "bar"
"baz" = 1.234
"nested" = {
"foo" = 12,
"bar" = "something"
}
}
`
var out testproto.DynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.StructVal)
valMap := out.StructVal.AsMap()
jsonVal, err := json.Marshal(valMap)
require.NoError(t, err)
expected := `{
"null": null,
"bool": true,
"foo": "bar",
"baz": 1.234,
"nested": {
"foo": 12,
"bar": "something"
}
}
`
require.JSONEq(t, expected, string(jsonVal))
}
func TestStructList(t *testing.T) {
hcl := `
struct_val = {
"list_int" = [
1,
2,
3,
]
"list_string": [
"abc",
"def"
]
"list_bool": [
true,
false
]
"list_maps" = [
{
"arrr" = "matey"
},
{
"hoist" = "the colors"
}
]
"list_list" = [
[
"hello",
"world",
null
]
]
}
`
var out testproto.DynamicWellKnown
err := Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.StructVal)
valMap := out.StructVal.AsMap()
jsonVal, err := json.Marshal(valMap)
require.NoError(t, err)
expected := `{
"list_int": [
1,
2,
3
],
"list_string": [
"abc",
"def"
],
"list_bool": [
true,
false
],
"list_maps": [
{
"arrr": "matey"
},
{
"hoist": "the colors"
}
],
"list_list": [
[
"hello",
"world",
null
]
]
}
`
require.JSONEq(t, expected, string(jsonVal))
}
func TestFunctionExecution(t *testing.T) {
hcl := `
primitives = primitive_defaults()
`
var out testproto.NestedAndCollections
var (
testType = cty.Capsule("type", reflect.TypeOf(testproto.Primitives{}))
test = function.New(&function.Spec{
Params: []function.Parameter{},
Type: function.StaticReturnType(testType),
Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) {
t := &testproto.Primitives{
StringVal: "test",
Int32Val: 10,
BoolVal: false,
}
return cty.CapsuleVal(testType, t), nil
},
})
)
err := UnmarshalOptions{
Functions: map[string]function.Function{"primitive_defaults": test},
}.Unmarshal([]byte(hcl), &out)
require.NoError(t, err)
require.NotNil(t, out.Primitives)
require.Equal(t, out.Primitives.StringVal, "test")
require.Equal(t, out.Primitives.Int32Val, int32(10))
require.Equal(t, out.Primitives.BoolVal, false)
}
func TestSkipFields(t *testing.T) {
u := UnmarshalOptions{}
hcl := `
any_val {
type_url = "hashicorp.consul.internal.protohcl.testproto.Primitives"
uint32_val = 10
}`
file, diags := hclparse.NewParser().ParseHCL([]byte(hcl), "")
require.False(t, diags.HasErrors())
decoder := u.bodyDecoder(file.Body)
decoder = decoder.SkipFields("type_url")
decoder = decoder.SkipFields("type_url", "uint32_val")
expected := map[string]struct{}{
"type_url": {},
"uint32_val": {},
}
require.Contains(t, fmt.Sprintf("%v", decoder), fmt.Sprintf("%v", expected))
}

View File

@ -0,0 +1,418 @@
package protohcl
import (
"fmt"
"time"
"github.com/zclconf/go-cty/cty"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/known/durationpb"
"google.golang.org/protobuf/types/known/emptypb"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
)
const (
// maximum time in seconds that a time.Time which comes from
// an RFC 3339 timestamp can represent
maxTimestampSeconds = 253402300799
// minimum time in seconds that a time.Time which comes from
// an RFC 3339 timestamp can represent. This is negative
// because RFC 3339 base time is year 0001 whereas time.Time
// starts in 1970
minTimestampSeconds = -62135596800
)
var (
// minTime is the earliest time representable as both an
// RFC 3339 timestamp and a time.Time value
minTime = time.Unix(minTimestampSeconds, 0)
// maxTime is the latest time respresentable as both an
// RFC 3339 timestamp and a time.Time value
maxTime = time.Unix(maxTimestampSeconds, 999999999)
)
type wktSchemaHint int
const (
notWellKnownType wktSchemaHint = iota
wellKnownBlock
wellKnownAttribute
)
// wellKnownTypeSchemaHint returns what sort of syntax should be used to represent
// the well known type field.
//
// NotWellKnownType - use attribute block syntax based on other information
// WellKnownAttribute - use attribute syntax
// WellKnownBlock - use block syntax
func wellKnownTypeSchemaHint(desc protoreflect.FieldDescriptor) wktSchemaHint {
if desc.Kind() != protoreflect.MessageKind {
return notWellKnownType
}
switch desc.Message().FullName() {
case "google.protobuf.DoubleValue":
return wellKnownAttribute
case "google.protobuf.FloatValue":
return wellKnownAttribute
case "google.protobuf.Int32Value":
return wellKnownAttribute
case "google.protobuf.Int64Value":
return wellKnownAttribute
case "google.protobuf.UInt32Value":
return wellKnownAttribute
case "google.protobuf.UInt64Value":
return wellKnownAttribute
case "google.protobuf.BoolValue":
return wellKnownAttribute
case "google.protobuf.StringValue":
return wellKnownAttribute
case "google.protobuf.BytesValue":
return wellKnownAttribute
case "google.protobuf.Empty":
// block syntax is used for Empty to allow transitioning to using
// a different proto message with fields in the future.
return wellKnownBlock
case "google.protobuf.Timestamp":
return wellKnownAttribute
case "google.protobuf.Duration":
return wellKnownAttribute
case "google.protobuf.Struct":
// as the Struct has completely free form fields that we cannot
// know about in advance we cannot use block syntax
return wellKnownAttribute
case "google.protobuf.Any":
return wellKnownBlock
default:
return notWellKnownType
}
}
func decodeAttributeToWellKnownType(desc protoreflect.FieldDescriptor, val cty.Value) (bool, protoreflect.Value, error) {
if desc.Kind() != protoreflect.MessageKind {
return false, protoreflect.Value{}, nil
}
switch desc.Message().FullName() {
case "google.protobuf.DoubleValue":
protoVal, err := protoDoubleWrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.FloatValue":
protoVal, err := protoFloatWrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.Int32Value":
protoVal, err := protoInt32WrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.Int64Value":
protoVal, err := protoInt64WrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.UInt32Value":
protoVal, err := protoUint32WrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.UInt64Value":
protoVal, err := protoUint64WrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.BoolValue":
protoVal, err := protoBoolWrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.StringValue":
protoVal, err := protoStringWrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.BytesValue":
protoVal, err := protoBytesWrapperFromCty(val)
return true, protoVal, err
case "google.protobuf.Empty":
protoVal, err := protoEmptyFromCty(val)
return true, protoVal, err
case "google.protobuf.Timestamp":
protoVal, err := protoTimestampFromCty(val)
return true, protoVal, err
case "google.protobuf.Duration":
protoVal, err := protoDurationFromCty(val)
return true, protoVal, err
case "google.protobuf.Struct":
protoVal, err := protoStructFromCty(val)
return true, protoVal, err
default:
return false, protoreflect.Value{}, nil
}
}
func protoWrapperFromBool(v bool) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.Bool(v).ProtoReflect())
}
func protoWrapperFromInt32(v int32) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.Int32(v).ProtoReflect())
}
func protoWrapperFromInt64(v int64) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.Int64(v).ProtoReflect())
}
func protoWrapperFromUint32(v uint32) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.UInt32(v).ProtoReflect())
}
func protoWrapperFromUint64(v uint64) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.UInt64(v).ProtoReflect())
}
func protoWrapperFromFloat(v float32) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.Float(v).ProtoReflect())
}
func protoWrapperFromDouble(v float64) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.Double(v).ProtoReflect())
}
func protoWrapperFromString(v string) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.String(v).ProtoReflect())
}
func protoWrapperFromBytes(v []byte) protoreflect.Value {
return protoreflect.ValueOfMessage(wrapperspb.Bytes(v).ProtoReflect())
}
func protoBoolWrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := boolFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromBool(v), nil
}
func protoInt32WrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := int32FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromInt32(v), nil
}
func protoInt64WrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := int64FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromInt64(v), nil
}
func protoUint32WrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := uint32FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromUint32(v), nil
}
func protoUint64WrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := uint64FromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromUint64(v), nil
}
func protoFloatWrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := floatFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromFloat(v), nil
}
func protoDoubleWrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := doubleFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromDouble(v), nil
}
func protoStringWrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := stringFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromString(v), nil
}
func protoBytesWrapperFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := bytesFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoWrapperFromBytes(v), nil
}
func protoEmptyFromCty(val cty.Value) (protoreflect.Value, error) {
var e emptypb.Empty
if val.IsNull() {
return protoreflect.Value{}, nil
}
valType := val.Type()
if (valType.IsObjectType() || valType.IsMapType()) && val.LengthInt() == 0 {
return protoreflect.ValueOfMessage(e.ProtoReflect()), nil
}
return protoreflect.Value{}, fmt.Errorf("well known empty type can only be represented as an hcl map/object - actual type %q", valType.FriendlyName())
}
func protoTimestampFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := stringFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
t, err := time.Parse(time.RFC3339Nano, v)
if err != nil {
return protoreflect.Value{}, fmt.Errorf("error parsing timestamp: %w", err)
}
if t.Before(minTime) || t.After(maxTime) {
return protoreflect.Value{}, fmt.Errorf("time is out of range %s to %s - %s", minTime.String(), maxTime.String(), v)
}
return protoreflect.ValueOfMessage(timestamppb.New(t).ProtoReflect()), nil
}
func protoDurationFromCty(val cty.Value) (protoreflect.Value, error) {
v, err := stringFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
d, err := time.ParseDuration(v)
if err != nil {
return protoreflect.Value{}, fmt.Errorf("error parsing string duration: %w", err)
}
return protoreflect.ValueOfMessage(durationpb.New(d).ProtoReflect()), nil
}
func protoStructFromCty(val cty.Value) (protoreflect.Value, error) {
s, err := protoStructObjectFromCty(val)
if err != nil {
return protoreflect.Value{}, err
}
return protoreflect.ValueOfMessage(s.ProtoReflect()), nil
}
func protoStructObjectFromCty(val cty.Value) (*structpb.Struct, error) {
valType := val.Type()
if !valType.IsObjectType() && !valType.IsMapType() {
return nil, fmt.Errorf("Struct type must be either an object or map type")
}
structValues := make(map[string]*structpb.Value)
for k, v := range val.AsValueMap() {
vType := v.Type()
if v.IsNull() {
structValues[k] = structpb.NewNullValue()
} else if vType.IsListType() || vType.IsSetType() || vType.IsTupleType() {
listVal, err := protoStructListValueFromCty(v)
if err != nil {
return nil, err
}
structValues[k] = structpb.NewListValue(listVal)
} else if vType.IsMapType() || vType.IsObjectType() {
objVal, err := protoStructObjectFromCty(v)
if err != nil {
return nil, err
}
structValues[k] = structpb.NewStructValue(objVal)
} else if vType.IsPrimitiveType() {
switch vType {
case cty.String:
stringVal, err := stringFromCty(v)
if err != nil {
return nil, err
}
structValues[k] = structpb.NewStringValue(stringVal)
case cty.Bool:
boolVal, err := boolFromCty(v)
if err != nil {
return nil, err
}
structValues[k] = structpb.NewBoolValue(boolVal)
case cty.Number:
doubleVal, err := doubleFromCty(v)
if err != nil {
return nil, err
}
structValues[k] = structpb.NewNumberValue(doubleVal)
default:
return nil, fmt.Errorf("unknown cty primitive type: %s", vType.FriendlyName())
}
} else {
return nil, fmt.Errorf("unsupported cty type: %s", vType.FriendlyName())
}
}
return &structpb.Struct{
Fields: structValues,
}, nil
}
func protoStructListValueFromCty(val cty.Value) (*structpb.ListValue, error) {
var values []*structpb.Value
var err error
val.ForEachElement(func(_ cty.Value, value cty.Value) bool {
vType := value.Type()
if value.IsNull() {
values = append(values, structpb.NewNullValue())
} else if vType.IsListType() || vType.IsSetType() || vType.IsTupleType() {
var listVal *structpb.ListValue
listVal, err = protoStructListValueFromCty(value)
if err != nil {
return true
}
values = append(values, structpb.NewListValue(listVal))
} else if vType.IsMapType() || vType.IsObjectType() {
var objVal *structpb.Struct
objVal, err = protoStructObjectFromCty(value)
if err != nil {
return true
}
values = append(values, structpb.NewStructValue(objVal))
} else if vType.IsPrimitiveType() {
switch vType {
case cty.String:
var stringVal string
stringVal, err = stringFromCty(value)
if err != nil {
return true
}
values = append(values, structpb.NewStringValue(stringVal))
case cty.Bool:
var boolVal bool
boolVal, err = boolFromCty(value)
if err != nil {
return true
}
values = append(values, structpb.NewBoolValue(boolVal))
case cty.Number:
var doubleVal float64
doubleVal, err = doubleFromCty(value)
if err != nil {
return true
}
values = append(values, structpb.NewNumberValue(doubleVal))
default:
err = fmt.Errorf("unknown cty primitive type: %s", vType.FriendlyName())
return true
}
} else {
err = fmt.Errorf("unsupported cty type: %s", vType.FriendlyName())
return true
}
return false
})
if err != nil {
return nil, err
}
return &structpb.ListValue{
Values: values,
}, nil
}

View File

@ -6,6 +6,7 @@ package resource
import (
"fmt"
"regexp"
"strings"
"sync"
"google.golang.org/protobuf/proto"
@ -171,3 +172,15 @@ func (r *TypeRegistry) Types() []Registration {
func ToGVK(resourceType *pbresource.Type) string {
return fmt.Sprintf("%s.%s.%s", resourceType.Group, resourceType.GroupVersion, resourceType.Kind)
}
func ParseGVK(gvk string) (*pbresource.Type, error) {
parts := strings.Split(gvk, ".")
if len(parts) != 3 {
return nil, fmt.Errorf("GVK string must be in the form <Group>.<GroupVersion>.<Kind>, got: %s", gvk)
}
return &pbresource.Type{
Group: parts[0],
GroupVersion: parts[1],
Kind: parts[2],
}, nil
}

View File

@ -0,0 +1,46 @@
package resourcehcl
import (
"errors"
"fmt"
"google.golang.org/protobuf/reflect/protoreflect"
"github.com/hashicorp/consul/internal/protohcl"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/proto-public/pbresource"
)
// anyProvider implements protohcl.AnyTypeProvider to infer the `Data` block
// type from `ID.Type`.
type anyProvider struct {
base protohcl.AnyTypeProvider
reg resource.Registry
}
func (p anyProvider) AnyType(ctx *protohcl.UnmarshalContext, decoder protohcl.MessageDecoder) (protoreflect.FullName, protohcl.MessageDecoder, error) {
if ctx.Name != "Data" {
return p.base.AnyType(ctx, decoder)
}
if ctx.Parent == nil || ctx.Parent.Message == nil {
return p.base.AnyType(ctx, decoder)
}
res, isResource := ctx.Parent.Message.Interface().(*pbresource.Resource)
if !isResource {
return p.base.AnyType(ctx, decoder)
}
resourceType := res.GetId().GetType()
if res == nil {
return "", nil, errors.New("ID.Type not found")
}
reg, ok := p.reg.Resolve(resourceType)
if !ok {
return "", nil, fmt.Errorf("unknown resource type: %s", resource.ToGVK(resourceType))
}
return reg.Proto.ProtoReflect().Descriptor().FullName(), decoder, nil
}

View File

@ -0,0 +1,35 @@
package resourcehcl
import (
"strings"
"google.golang.org/protobuf/reflect/protoreflect"
)
// fieldNamer implements protohcl.FieldNamer to name fields using PascalCase
// with support for acroynms (e.g. ID, TCP).
type fieldNamer struct{ acroynms []string }
func (n fieldNamer) NameField(fd protoreflect.FieldDescriptor) string {
camel := fd.JSONName()
upper := strings.ToUpper(camel)
for _, a := range n.acroynms {
if upper == a {
return a
}
}
return strings.ToUpper(camel[:1]) + camel[1:]
}
func (n fieldNamer) GetField(fds protoreflect.FieldDescriptors, name string) protoreflect.FieldDescriptor {
for _, a := range n.acroynms {
if name == a {
return fds.ByJSONName(strings.ToLower(a))
}
}
camel := strings.ToLower(name[:1]) + name[1:]
return fds.ByJSONName(camel)
}

View File

@ -0,0 +1 @@
gvk-no-arguments.hcl:2,14-15: Not enough function arguments; Function "gvk" expects 1 argument(s). Missing value for "GVK String".

View File

@ -0,0 +1,4 @@
ID {
Type = gvk()
Name = "foo"
}

View File

@ -0,0 +1 @@
invalid-group.hcl:3,13-17: Failed to unmarshal argument Group: expected value of type string but actual type is number

View File

@ -0,0 +1,8 @@
ID {
Type {
Group = 1234
GroupVersion = "v1"
Kind = "Artist"
}
Name = "foo"
}

View File

@ -0,0 +1 @@
invalid-gvk.hcl:2,10-14: Error in function call; Call to function "gvk" failed: GVK string must be in the form <Group>.<GroupVersion>.<Kind>, got: nope.

View File

@ -0,0 +1,4 @@
ID {
Type = gvk("nope")
Name = "foo"
}

View File

@ -0,0 +1 @@
invalid-metadata.hcl:6,12-8,2: Failed to unmarshal argument Metadata["foo"]: expected value of type string but actual type is tuple

View File

@ -0,0 +1,8 @@
ID {
Type = gvk("demo.v1.Artist")
Name = "korn"
}
Metadata = {
"foo" = ["bar"]
}

View File

@ -0,0 +1 @@
invalid-name.hcl:3,10-14: Failed to unmarshal argument Name: expected value of type string but actual type is number

View File

@ -0,0 +1,4 @@
ID {
Type = gvk("demo.v1.Artist")
Name = 1234
}

View File

@ -0,0 +1 @@
{"id":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}},"data":{"@type":"hashicorp.consul.internal.demo.v1.Artist","name":"Korn"}}

View File

@ -0,0 +1,8 @@
Data = {
Name = "Korn"
}
ID = {
Type = gvk("demo.v1.Artist")
Name = "korn"
}

View File

@ -0,0 +1 @@
{"id":{"type":{"group":"mesh","groupVersion":"v1alpha1","kind":"Upstreams"}},"data":{"@type":"hashicorp.consul.mesh.v1alpha1.Upstreams","workloads":{"prefixes":["api"]},"upstreams":[{"destinationRef":{"name":"db","type":{"group":"catalog","groupVersion":"v1alpha1","kind":"Service"}},"destinationPort":"tcp","ipPort":{"port":1234}}]}}

View File

@ -0,0 +1,33 @@
ID = {
Type = {
Group = "mesh"
GroupVersion = "v1alpha1"
Kind = "Upstreams"
}
}
Data = {
Workloads = {
Prefixes = ["api"]
}
Upstreams = [
{
DestinationRef = {
Type = {
Group = "catalog"
GroupVersion = "v1alpha1"
Kind = "Service"
}
Name = "db"
}
DestinationPort = "tcp"
IpPort = {
Port = 1234
}
}
]
}

View File

@ -0,0 +1 @@
{"id":{"name":"twisted-transistor","type":{"group":"demo","groupVersion":"v1","kind":"Album"}},"owner":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}}}

View File

@ -0,0 +1,9 @@
ID {
Type = gvk("demo.v1.Album")
Name = "twisted-transistor"
}
Owner {
Type = gvk("demo.v1.Artist")
Name = "korn"
}

View File

@ -0,0 +1 @@
{"id":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}},"metadata":{"foo":"bar"},"data":{"@type":"hashicorp.consul.internal.demo.v1.Artist","name":"Korn","genre":"GENRE_METAL"}}

View File

@ -0,0 +1,13 @@
ID {
Type = gvk("demo.v1.Artist")
Name = "korn"
}
Data {
Name = "Korn"
Genre = "GENRE_METAL"
}
Metadata = {
"foo" = "bar"
}

View File

@ -0,0 +1 @@
{"id":{"name":"korn","type":{"group":"demo","groupVersion":"v1","kind":"Artist"}}}

View File

@ -0,0 +1,8 @@
ID {
Type {
Group = "demo"
GroupVersion = "v1"
Kind = "Artist"
}
Name = "korn"
}

View File

@ -0,0 +1 @@
unknown-field-block.hcl:2,3-6: Unsupported argument; An argument named "Foo" is not expected here.

View File

@ -0,0 +1,3 @@
ID {
Foo = "bar"
}

View File

@ -0,0 +1 @@
unknown-field-object.hcl:1,6-3,2: Unsupported argument; An argument named "Foo" is not expected here.

View File

@ -0,0 +1,3 @@
ID = {
Foo = "bar"
}

View File

@ -0,0 +1 @@
error getting type for Any field: unknown resource type: foo.bar.Baz

View File

@ -0,0 +1,8 @@
ID {
Type = gvk("foo.bar.Baz")
Name = "qux"
}
Data {
Foo = "bar"
}

View File

@ -0,0 +1 @@
{"id":{"name":"api","type":{"group":"mesh","groupVersion":"v1alpha1","kind":"Upstreams"}},"data":{"@type":"hashicorp.consul.mesh.v1alpha1.Upstreams","workloads":{"prefixes":["api"]},"upstreams":[{"destinationRef":{"name":"db","type":{"group":"catalog","groupVersion":"v1alpha1","kind":"Service"}},"destinationPort":"tcp","ipPort":{"port":1234}}]}}

View File

@ -0,0 +1,25 @@
ID {
Type = gvk("mesh.v1alpha1.Upstreams")
Name = "api"
}
Data {
Workloads {
Prefixes = ["api"]
}
Upstreams = [
{
DestinationRef = {
Type = gvk("catalog.v1alpha1.Service")
Name = "db"
}
DestinationPort = "tcp"
IpPort = {
Port = 1234
}
}
]
}

View File

@ -0,0 +1,52 @@
package resourcehcl
import (
"reflect"
"github.com/zclconf/go-cty/cty"
"github.com/zclconf/go-cty/cty/function"
"github.com/hashicorp/consul/internal/protohcl"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/proto-public/pbresource"
)
// Unmarshal the given HCL source into a resource.
func Unmarshal(src []byte, reg resource.Registry) (*pbresource.Resource, error) {
return UnmarshalOptions{}.Unmarshal(src, reg)
}
type UnmarshalOptions struct{ SourceFileName string }
// Unmarshal the given HCL source into a resource.
func (u UnmarshalOptions) Unmarshal(src []byte, reg resource.Registry) (*pbresource.Resource, error) {
var out pbresource.Resource
err := (protohcl.UnmarshalOptions{
SourceFileName: u.SourceFileName,
AnyTypeProvider: anyProvider{
base: &protohcl.AnyTypeURLProvider{TypeURLFieldName: "Type"},
reg: reg,
},
FieldNamer: fieldNamer{acroynms: []string{"ID", "TCP", "UDP", "HTTP"}},
Functions: map[string]function.Function{"gvk": gvk},
}).Unmarshal(src, &out)
return &out, err
}
var (
typeType = cty.Capsule("type", reflect.TypeOf(pbresource.Type{}))
gvk = function.New(&function.Spec{
Params: []function.Parameter{
{Name: "GVK String", Type: cty.String},
},
Type: function.StaticReturnType(typeType),
Impl: func(args []cty.Value, _ cty.Type) (cty.Value, error) {
t, err := resource.ParseGVK(args[0].AsString())
if err != nil {
return cty.NilVal, err
}
return cty.CapsuleVal(typeType, t), nil
},
})
)

View File

@ -0,0 +1,103 @@
package resourcehcl_test
import (
"flag"
"fmt"
"os"
"path"
"testing"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protojson"
"github.com/hashicorp/consul/internal/mesh"
"github.com/hashicorp/consul/internal/resource"
"github.com/hashicorp/consul/internal/resource/demo"
"github.com/hashicorp/consul/internal/resourcehcl"
"github.com/hashicorp/consul/proto-public/pbresource"
"github.com/hashicorp/consul/proto/private/prototest"
)
var update = flag.Bool("update", false, "update golden files")
func TestUnmarshal(t *testing.T) {
entries, err := os.ReadDir("./testdata")
require.NoError(t, err)
read := func(t *testing.T, path string) ([]byte, bool) {
t.Helper()
bytes, err := os.ReadFile(fmt.Sprintf("./testdata/%s", path))
switch {
case err == nil:
return bytes, true
case os.IsNotExist(err):
return nil, false
}
t.Fatalf("failed to read file %s %v", path, err)
return nil, false
}
write := func(t *testing.T, path string, src []byte) {
t.Helper()
require.NoError(t, os.WriteFile(fmt.Sprintf("./testdata/%s", path), src, 0o600))
}
for _, entry := range entries {
name := entry.Name()
ext := path.Ext(name)
if ext != ".hcl" {
continue
}
base := name[0 : len(name)-len(ext)]
t.Run(base, func(t *testing.T) {
input, _ := read(t, name)
registry := resource.NewRegistry()
demo.RegisterTypes(registry)
mesh.RegisterTypes(registry)
output, err := resourcehcl.UnmarshalOptions{SourceFileName: name}.
Unmarshal(input, registry)
if *update {
if err == nil {
json, err := protojson.Marshal(output)
require.NoError(t, err)
write(t, base+".golden", json)
} else {
write(t, base+".error", []byte(err.Error()))
}
}
goldenJSON, haveGoldenJSON := read(t, base+".golden")
goldenError, haveGoldenError := read(t, base+".error")
if haveGoldenError && haveGoldenJSON {
t.Fatalf("both %s.golden and %s.error exist, delete one", base, base)
}
if !haveGoldenError && !haveGoldenJSON && !*update {
t.Fatalf("neither %s.golden or %s.error exist, run the tests again with the -update flag to create one", base, base)
}
if haveGoldenError {
require.Error(t, err)
require.Equal(t, string(goldenError), err.Error())
}
if haveGoldenJSON {
require.NoError(t, err)
var exp pbresource.Resource
require.NoError(t, protojson.Unmarshal(goldenJSON, &exp))
prototest.AssertDeepEqual(t, &exp, output)
}
})
}
}