Repository: knative-sandbox/eventing-kafka
Pull request #1258 (2022-10-18 02:09:47)

[main] Upgrade to latest dependencies
Bump after eventing cut -nak3

/cc knative-sandbox/eventing-writers
/assign knative-sandbox/eventing-writers

Produced by: knative-sandbox/knobots/actions/update-deps

codecov[bot]: # [Codecov](https://codecov.io/gh/knative-sandbox/eventing-kafka/pull/1258?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) Report
> Merging [#1258](https://codecov.io/gh/knative-sandbox/eventing-kafka/pull/1258?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) (b908c77) into [main](https://codecov.io/gh/knative-sandbox/eventing-kafka/commit/cbd23ae03d4ecbf165d8333d486f457f442f486e?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox) (cbd23ae) will **not change** coverage.
> The diff coverage is `n/a`.

```diff
@@           Coverage Diff           @@
##             main    #1258   +/-   ##
=======================================
  Coverage   74.93%   74.93%           
=======================================
  Files         128      128           
  Lines        9017     9017           
=======================================
  Hits         6757     6757           
  Misses       2029     2029           
  Partials      231      231           
```



Help us with your feedback. Take ten seconds to tell us [how you rate us](https://about.codecov.io/nps?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox). Have a feature suggestion? [Share it here.](https://app.codecov.io/gh/feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=knative-sandbox)

nak3: /lgtm
/approve
knative-prow[bot]: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/knative-sandbox/eventing-kafka/pull/1258#" title="Author self-approved">knative-automation</a>*, *<a href="https://github.com/knative-sandbox/eventing-kafka/pull/1258#issuecomment-1281822422" title="Approved">nak3</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=knative-sandbox%2Feventing-kafka).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/knative-sandbox/eventing-kafka/blob/main/OWNERS)~~ [nak3]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->

Patch:
diff --git a/go.mod b/go.mod
index 0f87fc428..57a4cf5c8 100644
--- a/go.mod
+++ b/go.mod
@@ -30,7 +30,7 @@ require (
 	k8s.io/client-go v0.25.2
 	k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
 	knative.dev/control-protocol v0.0.0-20221017021456-3e2f8785943b
-	knative.dev/eventing v0.34.1-0.20221013172353-24adf198c60c
+	knative.dev/eventing v0.34.1-0.20221018032010-0fe923cd8a5b
 	knative.dev/hack v0.0.0-20221010154335-3fdc50b9c24a
 	knative.dev/pkg v0.0.0-20221011175852-714b7630a836
 	knative.dev/reconciler-test v0.0.0-20221017014457-090970c9ca3c
@@ -117,7 +117,7 @@ require (
 	github.com/modern-go/reflect2 v1.0.2 // indirect
 	github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
 	github.com/openzipkin/zipkin-go v0.3.0 // indirect
-	github.com/pelletier/go-toml/v2 v2.0.0-beta.2 // indirect
+	github.com/pelletier/go-toml/v2 v2.0.5 // indirect
 	github.com/pierrec/lz4 v2.6.1+incompatible // indirect
 	github.com/pkg/errors v0.9.1 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
diff --git a/go.sum b/go.sum
index c1c4cd3db..1a785844d 100644
--- a/go.sum
+++ b/go.sum
@@ -510,8 +510,8 @@ github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnh
 github.com/openzipkin/zipkin-go v0.3.0 h1:XtuXmOLIXLjiU2XduuWREDT0LOKtSgos/g7i7RYyoZQ=
 github.com/openzipkin/zipkin-go v0.3.0/go.mod h1:4c3sLeE8xjNqehmF5RpAFLPLJxXscc0R4l6Zg0P1tTQ=
 github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
-github.com/pelletier/go-toml/v2 v2.0.0-beta.2 h1:f/g66OWmYXmVnYL3UAhqpM9YuWKFR2vjYfFNSDQcHPQ=
-github.com/pelletier/go-toml/v2 v2.0.0-beta.2/go.mod h1:+X+aW6gUj6Hda43TeYHVCIvYNG/jqY/8ZFXAeXXHl+Q=
+github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
+github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas=
 github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
 github.com/pierrec/lz4 v0.0.0-20190327172049-315a67e90e41/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
 github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
@@ -1161,8 +1161,8 @@ k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/l
 k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
 knative.dev/control-protocol v0.0.0-20221017021456-3e2f8785943b h1:PP9M/LtGwrGLbr1CjrLzuFU8HcrjB/qtoHPtqkg1M0E=
 knative.dev/control-protocol v0.0.0-20221017021456-3e2f8785943b/go.mod h1:v9fqtPTwQKwJAeUyFjyo4teoFA0EanxFVrtcQELTrRY=
-knative.dev/eventing v0.34.1-0.20221013172353-24adf198c60c h1:iwyvqeijTtg2E0Y1Cmu9QONI7uBeO7GpObehT86WnHA=
-knative.dev/eventing v0.34.1-0.20221013172353-24adf198c60c/go.mod h1:7z3CSDln/yWU1JJ/WQcUeqeImLyiyUMxCXQkw0Mi7nQ=
+knative.dev/eventing v0.34.1-0.20221018032010-0fe923cd8a5b h1:fgr/yRUg7nHSP0GM4eVO9eRDNV129SrSL3NfPojL6KE=
+knative.dev/eventing v0.34.1-0.20221018032010-0fe923cd8a5b/go.mod h1:MEqB5frQ5jQ2/A+WHpDU2VNLXum+4o7TiMhTdCvji9w=
 knative.dev/hack v0.0.0-20221010154335-3fdc50b9c24a h1:yfq1OMrkyYkxDeM0pmAOeN4YF16R/WG0C+VvLBeq4uc=
 knative.dev/hack v0.0.0-20221010154335-3fdc50b9c24a/go.mod h1:yk2OjGDsbEnQjfxdm0/HJKS2WqTLEFg/N6nUs6Rqx3Q=
 knative.dev/pkg v0.0.0-20221011175852-714b7630a836 h1:0N7Zo/O+xeUUebJPm9keBaGclrUoEbljr3J1MsqtaIM=
diff --git a/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/v2/LICENSE b/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/v2/LICENSE
index 3a38ac28b..6839d51cd 100644
--- a/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/v2/LICENSE
+++ b/third_party/VENDOR-LICENSE/github.com/pelletier/go-toml/v2/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2013 - 2021 Thomas Pelletier, Eric Anderton
+Copyright (c) 2013 - 2022 Thomas Pelletier, Eric Anderton
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/github.com/pelletier/go-toml/v2/.gitattributes b/vendor/github.com/pelletier/go-toml/v2/.gitattributes
new file mode 100644
index 000000000..34a0a21a3
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/.gitattributes
@@ -0,0 +1,4 @@
+* text=auto
+
+benchmark/benchmark.toml text eol=lf
+testdata/** text eol=lf
diff --git a/vendor/github.com/pelletier/go-toml/v2/.gitignore b/vendor/github.com/pelletier/go-toml/v2/.gitignore
index e6ba63a5c..a69e2b0eb 100644
--- a/vendor/github.com/pelletier/go-toml/v2/.gitignore
+++ b/vendor/github.com/pelletier/go-toml/v2/.gitignore
@@ -3,3 +3,4 @@ fuzz/
 cmd/tomll/tomll
 cmd/tomljson/tomljson
 cmd/tomltestgen/tomltestgen
+dist
\ No newline at end of file
diff --git a/vendor/github.com/pelletier/go-toml/v2/.golangci.toml b/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
index fdf167b4a..067db5517 100644
--- a/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
+++ b/vendor/github.com/pelletier/go-toml/v2/.golangci.toml
@@ -60,7 +60,7 @@ enable = [
     # "nlreturn",
     "noctx",
     "nolintlint",
-    "paralleltest",
+    #"paralleltest",
     "prealloc",
     "predeclared",
     "revive",
diff --git a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
new file mode 100644
index 000000000..3aa1840ec
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
@@ -0,0 +1,123 @@
+before:
+  hooks:
+    - go mod tidy
+    - go fmt ./...
+    - go test ./...
+builds:
+  - id: tomll
+    main: ./cmd/tomll
+    binary: tomll
+    env:
+      - CGO_ENABLED=0
+    flags:
+      - -trimpath
+    ldflags:
+      - -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}}
+    mod_timestamp: '{{ .CommitTimestamp }}'
+    targets:
+      - linux_amd64
+      - linux_arm64
+      - linux_arm
+      - windows_amd64
+      - windows_arm64
+      - windows_arm
+      - darwin_amd64
+      - darwin_arm64
+  - id: tomljson
+    main: ./cmd/tomljson
+    binary: tomljson
+    env:
+      - CGO_ENABLED=0
+    flags:
+      - -trimpath
+    ldflags:
+      - -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}}
+    mod_timestamp: '{{ .CommitTimestamp }}'
+    targets:
+      - linux_amd64
+      - linux_arm64
+      - linux_arm
+      - windows_amd64
+      - windows_arm64
+      - windows_arm
+      - darwin_amd64
+      - darwin_arm64
+  - id: jsontoml
+    main: ./cmd/jsontoml
+    binary: jsontoml
+    env:
+      - CGO_ENABLED=0
+    flags:
+      - -trimpath
+    ldflags:
+      - -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}}
+    mod_timestamp: '{{ .CommitTimestamp }}'
+    targets:
+      - linux_amd64
+      - linux_arm64
+      - linux_arm
+      - windows_amd64
+      - windows_arm64
+      - windows_arm
+      - darwin_amd64
+      - darwin_arm64
+universal_binaries:
+  - id: tomll
+    replace: true
+    name_template: tomll
+  - id: tomljson
+    replace: true
+    name_template: tomljson
+  - id: jsontoml
+    replace: true
+    name_template: jsontoml
+archives:
+- id: jsontoml
+  format: tar.xz
+  builds:
+    - jsontoml
+  files:
+  - none*
+  name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}"
+- id: tomljson
+  format: tar.xz
+  builds:
+    - tomljson
+  files:
+  - none*
+  name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}"
+- id: tomll
+  format: tar.xz
+  builds:
+    - tomll
+  files:
+  - none*
+  name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}"
+dockers:
+  - id: tools
+    goos: linux
+    goarch: amd64
+    ids:
+      - jsontoml
+      - tomljson
+      - tomll
+    image_templates:
+      - "ghcr.io/pelletier/go-toml:latest"
+      - "ghcr.io/pelletier/go-toml:{{ .Tag }}"
+      - "ghcr.io/pelletier/go-toml:v{{ .Major }}"
+    skip_push: false
+checksum:
+  name_template: 'sha256sums.txt'
+snapshot:
+  name_template: "{{ incpatch .Version }}-next"
+release:
+  github:
+    owner: pelletier
+    name: go-toml
+  draft: true
+  prerelease: auto
+  mode: replace
+changelog:
+  use: github-native
+announce:
+  skip: true
diff --git a/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md b/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
index 59658d39d..04dd12bcb 100644
--- a/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
+++ b/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
@@ -155,6 +155,8 @@ Checklist:
 - Does not introduce backward-incompatible changes (unless discussed).
 - Has relevant doc changes.
 - Benchstat does not show performance regression.
+- Pull request is [labeled appropriately][pr-labels].
+- Title will be understandable in the changelog.
 
 1. Merge using "squash and merge".
 2. Make sure to edit the commit message to keep all the useful information
@@ -163,13 +165,25 @@ Checklist:
 
 ### New release
 
-1. Go to [releases][releases]. Click on "X commits to master since this
-   release".
-2. Make note of all the changes. Look for backward incompatible changes,
-   new features, and bug fixes.
-3. Pick the new version using the above and semver.
-4. Create a [new release][new-release].
-5. Follow the same format as [1.1.0][release-110].
+1. Decide on the next version number. Use semver.
+2. Generate release notes using [`gh`][gh]. Example:
+```
+$ gh api -X POST \
+  -F tag_name='v2.0.0-beta.5' \
+  -F target_commitish='v2' \
+  -F previous_tag_name='v2.0.0-beta.4' \
+  --jq '.body' \
+  repos/pelletier/go-toml/releases/generate-notes
+```
+3. Look for "Other changes". That would indicate a pull request not labeled
+   properly. Tweak labels and pull request titles until changelog looks good for
+   users.
+4. [Draft new release][new-release].
+5. Fill tag and target with the same value used to generate the changelog.
+6. Set title to the new tag value.
+7. Paste the generated changelog.
+8. Check "create discussion", in the "Releases" category.
+9. Check pre-release if new version is an alpha or beta.
 
 [issues-tracker]: https://github.com/pelletier/go-toml/issues
 [bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md
@@ -177,6 +191,6 @@ Checklist:
 [readme]: ./README.md
 [fork]: https://help.github.com/articles/fork-a-repo
 [pull-request]: https://help.github.com/en/articles/creating-a-pull-request
-[releases]: https://github.com/pelletier/go-toml/releases
 [new-release]: https://github.com/pelletier/go-toml/releases/new
-[release-110]: https://github.com/pelletier/go-toml/releases/tag/v1.1.0
+[gh]: https://github.com/cli/cli
+[pr-labels]: https://github.com/pelletier/go-toml/blob/v2/.github/release.yml
diff --git a/vendor/github.com/pelletier/go-toml/v2/Dockerfile b/vendor/github.com/pelletier/go-toml/v2/Dockerfile
new file mode 100644
index 000000000..b9e933237
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/Dockerfile
@@ -0,0 +1,5 @@
+FROM scratch
+ENV PATH "$PATH:/bin"
+COPY tomll /bin/tomll
+COPY tomljson /bin/tomljson
+COPY jsontoml /bin/jsontoml
diff --git a/vendor/github.com/pelletier/go-toml/v2/LICENSE b/vendor/github.com/pelletier/go-toml/v2/LICENSE
index 3a38ac28b..6839d51cd 100644
--- a/vendor/github.com/pelletier/go-toml/v2/LICENSE
+++ b/vendor/github.com/pelletier/go-toml/v2/LICENSE
@@ -1,6 +1,6 @@
 The MIT License (MIT)
 
-Copyright (c) 2013 - 2021 Thomas Pelletier, Eric Anderton
+Copyright (c) 2013 - 2022 Thomas Pelletier, Eric Anderton
 
 Permission is hereby granted, free of charge, to any person obtaining a copy
 of this software and associated documentation files (the "Software"), to deal
diff --git a/vendor/github.com/pelletier/go-toml/v2/README.md b/vendor/github.com/pelletier/go-toml/v2/README.md
index 876f31e56..a63c3a796 100644
--- a/vendor/github.com/pelletier/go-toml/v2/README.md
+++ b/vendor/github.com/pelletier/go-toml/v2/README.md
@@ -4,32 +4,25 @@ Go library for the [TOML](https://toml.io/en/) format.
 
 This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
 
+[🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
 
-## Development status
-
-This is the upcoming major version of go-toml. It is currently in active
-development. As of release v2.0.0-beta.1, the library has reached feature parity
-with v1, and fixes a lot known bugs and performance issues along the way.
-
-If you do not need the advanced document editing features of v1, you are
-encouraged to try out this version.
-
-👉 [Roadmap for v2](https://github.com/pelletier/go-toml/discussions/506).
-
+[💬 Anything else](https://github.com/pelletier/go-toml/discussions)
 
 ## Documentation
 
-Full API, examples, and implementation notes are available in the Go documentation.
+Full API, examples, and implementation notes are available in the Go
+documentation.
 
 [![Go Reference](https://pkg.go.dev/badge/github.com/pelletier/go-toml/v2.svg)](https://pkg.go.dev/github.com/pelletier/go-toml/v2)
 
-
 ## Import
 
 ```go
 import "github.com/pelletier/go-toml/v2"
 ```
 
+See [Modules](#Modules).
+
 ## Features
 
 ### Stdlib behavior
@@ -40,20 +33,21 @@ standard library's `encoding/json`.
 ### Performance
 
 While go-toml favors usability, it is written with performance in mind. Most
-operations should not be shockingly slow.
+operations should not be shockingly slow. See [benchmarks](#benchmarks).
 
 ### Strict mode
 
 `Decoder` can be set to "strict mode", which makes it error when some parts of
-the TOML document was not prevent in the target structure. This is a great way
+the TOML document was not present in the target structure. This is a great way
 to check for typos. [See example in the documentation][strict].
 
-[strict]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Decoder.SetStrict
+[strict]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Decoder.DisallowUnknownFields
 
 ### Contextualized errors
 
-When decoding errors occur, go-toml returns [`DecodeError`][decode-err]), which
-contains a human readable contextualized version of the error. For example:
+When most decoding errors occur, go-toml returns [`DecodeError`][decode-err]),
+which contains a human readable contextualized version of the error. For
+example:
 
 ```
 2| key1 = "value1"
@@ -146,6 +140,101 @@ fmt.Println(string(b))
 
 [marshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Marshal
 
+## Benchmarks
+
+Execution time speedup compared to other Go TOML libraries:
+
+<table>
+    <thead>
+        <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
+    </thead>
+    <tbody>
+        <tr><td>Marshal/HugoFrontMatter-2</td><td>1.9x</td><td>1.9x</td></tr>
+        <tr><td>Marshal/ReferenceFile/map-2</td><td>1.7x</td><td>1.8x</td></tr>
+        <tr><td>Marshal/ReferenceFile/struct-2</td><td>2.2x</td><td>2.5x</td></tr>
+        <tr><td>Unmarshal/HugoFrontMatter-2</td><td>2.9x</td><td>2.9x</td></tr>
+        <tr><td>Unmarshal/ReferenceFile/map-2</td><td>2.6x</td><td>2.9x</td></tr>
+        <tr><td>Unmarshal/ReferenceFile/struct-2</td><td>4.4x</td><td>5.3x</td></tr>
+     </tbody>
+</table>
+<details><summary>See more</summary>
+<p>The table above has the results of the most common use-cases. The table below
+contains the results of all benchmarks, including unrealistic ones. It is
+provided for completeness.</p>
+
+<table>
+    <thead>
+        <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
+    </thead>
+    <tbody>
+        <tr><td>Marshal/SimpleDocument/map-2</td><td>1.8x</td><td>2.9x</td></tr>
+        <tr><td>Marshal/SimpleDocument/struct-2</td><td>2.7x</td><td>4.2x</td></tr>
+        <tr><td>Unmarshal/SimpleDocument/map-2</td><td>4.5x</td><td>3.1x</td></tr>
+        <tr><td>Unmarshal/SimpleDocument/struct-2</td><td>6.2x</td><td>3.9x</td></tr>
+        <tr><td>UnmarshalDataset/example-2</td><td>3.1x</td><td>3.5x</td></tr>
+        <tr><td>UnmarshalDataset/code-2</td><td>2.3x</td><td>3.1x</td></tr>
+        <tr><td>UnmarshalDataset/twitter-2</td><td>2.5x</td><td>2.6x</td></tr>
+        <tr><td>UnmarshalDataset/citm_catalog-2</td><td>2.1x</td><td>2.2x</td></tr>
+        <tr><td>UnmarshalDataset/canada-2</td><td>1.6x</td><td>1.3x</td></tr>
+        <tr><td>UnmarshalDataset/config-2</td><td>4.3x</td><td>3.2x</td></tr>
+        <tr><td>[Geo mean]</td><td>2.7x</td><td>2.8x</td></tr>
+     </tbody>
+</table>
+<p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>
+</details>
+
+## Modules
+
+go-toml uses Go's standard modules system.
+
+Installation instructions:
+
+- Go ≥ 1.16: Nothing to do. Use the import in your code. The `go` command deals
+  with it automatically.
+- Go ≥ 1.13: `GO111MODULE=on go get github.com/pelletier/go-toml/v2`.
+
+In case of trouble: [Go Modules FAQ][mod-faq].
+
+[mod-faq]: https://github.com/golang/go/wiki/Modules#why-does-installing-a-tool-via-go-get-fail-with-error-cannot-find-main-module
+
+## Tools
+
+Go-toml provides three handy command line tools:
+
+ * `tomljson`: Reads a TOML file and outputs its JSON representation.
+
+    ```
+    $ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest
+    $ tomljson --help
+    ```
+
+ * `jsontoml`: Reads a JSON file and outputs a TOML representation.
+
+    ```
+    $ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest
+    $ jsontoml --help
+    ```
+
+ * `tomll`: Lints and reformats a TOML file.
+
+    ```
+    $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest
+    $ tomll --help
+    ```
+
+### Docker image
+
+Those tools are also available as a [Docker image][docker]. For example, to use
+`tomljson`:
+
+```
+docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml
+```
+
+Multiple versions are availble on [ghcr.io][docker].
+
+[docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml
+
 ## Migrating from v1
 
 This section describes the differences between v1 and v2, with some pointers on
@@ -187,7 +276,7 @@ d := doc{
 }
 
 data := `
-[A]                                                                                                                           
+[A]
 B = "After"
 `
 
@@ -248,6 +337,45 @@ This method was not widely used, poorly defined, and added a lot of complexity.
 A similar effect can be achieved by implementing the `encoding.TextUnmarshaler`
 interface and use strings.
 
+#### Support for `default` struct tag has been dropped
+
+This feature adds complexity and a poorly defined API for an effect that can be
+accomplished outside of the library.
+
+It does not seem like other format parsers in Go support that feature (the
+project referenced in the original ticket #202 has not been updated since 2017).
+Given that go-toml v2 should not touch values not in the document, the same
+effect can be achieved by pre-filling the struct with defaults (libraries like
+[go-defaults][go-defaults] can help). Also, string representation is not well
+defined for all types: it creates issues like #278.
+
+The recommended replacement is pre-filling the struct before unmarshaling.
+
+[go-defaults]: https://github.com/mcuadros/go-defaults
+
+#### `toml.Tree` replacement
+
+This structure was the initial attempt at providing a document model for
+go-toml. It allows manipulating the structure of any document, encoding and
+decoding from their TOML representation. While a more robust feature was
+initially planned in go-toml v2, this has been ultimately [removed from
+scope][nodoc] of this library, with no plan to add it back at the moment. The
+closest equivalent at the moment would be to unmarshal into an `interface{}` and
+use type assertions and/or reflection to manipulate the arbitrary
+structure. However this would fall short of providing all of the TOML features
+such as adding comments and be specific about whitespace.
+
+
+#### `toml.Position` are not retrievable anymore
+
+The API for retrieving the position (line, column) of a specific TOML element do
+not exist anymore. This was done to minimize the amount of concepts introduced
+by the library (query path), and avoid the performance hit related to storing
+positions in the absence of a document model, for a feature that seemed to have
+little use. Errors however have gained more detailed position
+information. Position retrieval seems better fitted for a document model, which
+has been [removed from the scope][nodoc] of go-toml v2 at the moment.
+
 ### Encoding / Marshal
 
 #### Default struct fields order
@@ -283,14 +411,14 @@ fmt.Println("v2:\n" + string(b))
 ```
 
 There is no way to make v2 encoder behave like v1. A workaround could be to
-manually sort the fields alphabetically in the struct definition.
+manually sort the fields alphabetically in the struct definition, or generate
+struct types using `reflect.StructOf`.
 
 #### No indentation by default
 
 V1 automatically indents content of tables by default. V2 does not. However the
 same behavior can be obtained using [`Encoder.SetIndentTables`][sit]. For example:
 
-
 ```go
 data := map[string]interface{}{
 	"table": map[string]string{
@@ -312,15 +440,15 @@ fmt.Println("v2 Encoder:\n" + string(buf.Bytes()))
 
 // Output:
 // v1:
-// 
+//
 // [table]
 //   key = "value"
-// 
+//
 // v2:
 // [table]
 // key = 'value'
-// 
-// 
+//
+//
 // v2 Encoder:
 // [table]
 //   key = 'value'
@@ -332,7 +460,9 @@ fmt.Println("v2 Encoder:\n" + string(buf.Bytes()))
 
 V1 always uses double quotes (`"`) around strings and keys that cannot be
 represented bare (unquoted). V2 uses single quotes instead by default (`'`),
-unless a character cannot be represented, then falls back to double quotes.
+unless a character cannot be represented, then falls back to double quotes. As a
+result of this change, `Encoder.QuoteMapKeys` has been removed, as it is not
+useful anymore.
 
 There is no way to make v2 encoder behave like v1.
 
@@ -347,6 +477,76 @@ There is no way to make v2 encoder behave like v1.
 
 [tm]: https://golang.org/pkg/encoding/#TextMarshaler
 
+#### `Encoder.CompactComments` has been removed
+
+Emitting compact comments is now the default behavior of go-toml. This option
+is not necessary anymore.
+
+#### Struct tags have been merged
+
+V1 used to provide multiple struct tags: `comment`, `commented`, `multiline`,
+`toml`, and `omitempty`. To behave more like the standard library, v2 has merged
+`toml`, `multiline`, and `omitempty`. For example:
+
+```go
+type doc struct {
+	// v1
+	F string `toml:"field" multiline:"true" omitempty:"true"`
+	// v2
+	F string `toml:"field,multiline,omitempty"`
+}
+```
+
+Has a result, the `Encoder.SetTag*` methods have been removed, as there is just
+one tag now.
+
+
+#### `commented` tag has been removed
+
+There is no replacement for the `commented` tag. This feature would be better
+suited in a proper document model for go-toml v2, which has been [cut from
+scope][nodoc] at the moment.
+
+#### `Encoder.ArraysWithOneElementPerLine` has been renamed
+
+The new name is `Encoder.SetArraysMultiline`. The behavior should be the same.
+
+#### `Encoder.Indentation` has been renamed
+
+The new name is `Encoder.SetIndentSymbol`. The behavior should be the same.
+
+
+#### Embedded structs behave like stdlib
+
+V1 defaults to merging embedded struct fields into the embedding struct. This
+behavior was unexpected because it does not follow the standard library. To
+avoid breaking backward compatibility, the `Encoder.PromoteAnonymous` method was
+added to make the encoder behave correctly. Given backward compatibility is not
+a problem anymore, v2 does the right thing by default: it follows the behavior
+of `encoding/json`. `Encoder.PromoteAnonymous` has been removed.
+
+[nodoc]: https://github.com/pelletier/go-toml/discussions/506#discussioncomment-1526038
+
+### `query`
+
+go-toml v1 provided the [`go-toml/query`][query] package. It allowed to run
+JSONPath-style queries on TOML files. This feature is not available in v2. For a
+replacement, check out [dasel][dasel].
+
+This package has been removed because it was essentially not supported anymore
+(last commit May 2020), increased the complexity of the code base, and more
+complete solutions exist out there.
+
+[query]: https://github.com/pelletier/go-toml/tree/f99d6bbca119636aeafcf351ee52b3d202782627/query
+[dasel]: https://github.com/TomWright/dasel
+
+## Versioning
+
+Go-toml follows [Semantic Versioning](http://semver.org/). The supported version
+of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of
+this document. The last two major versions of Go are supported
+(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)).
+
 ## License
 
 The MIT License (MIT). Read [LICENSE](LICENSE).
diff --git a/vendor/github.com/pelletier/go-toml/v2/SECURITY.md b/vendor/github.com/pelletier/go-toml/v2/SECURITY.md
new file mode 100644
index 000000000..b2f21cfc9
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/SECURITY.md
@@ -0,0 +1,19 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version    | Supported          |
+| ---------- | ------------------ |
+| Latest 2.x | :white_check_mark: |
+| All 1.x    | :x:                |
+| All 0.x    | :x:                |
+
+## Reporting a Vulnerability
+
+Email a vulnerability report to `security@pelletier.codes`. Make sure to include
+as many details as possible to reproduce the vulnerability. This is a
+side-project: I will try to get back to you as quickly as possible, time
+permitting in my personal life. Providing a working patch helps very much!
diff --git a/vendor/github.com/pelletier/go-toml/v2/ci.sh b/vendor/github.com/pelletier/go-toml/v2/ci.sh
index 75d7008b3..d916c5f23 100644
--- a/vendor/github.com/pelletier/go-toml/v2/ci.sh
+++ b/vendor/github.com/pelletier/go-toml/v2/ci.sh
@@ -39,6 +39,12 @@ benchmark [OPTIONS...] [BRANCH]
         -d      Compare benchmarks of HEAD with BRANCH using benchstats. In
                 this form the BRANCH argument is required.
 
+        -a      Compare benchmarks of HEAD against go-toml v1 and
+                BurntSushi/toml.
+
+        -html   When used with -a, emits the output as HTML, ready to be
+                embedded in the README.
+
 coverage [OPTIONS...] [BRANCH]
 
     Generates code coverage.
@@ -70,7 +76,8 @@ cover() {
     fi
 
     pushd "$dir"
-    go test -covermode=atomic -coverprofile=coverage.out ./...
+    go test -covermode=atomic  -coverpkg=./... -coverprofile=coverage.out.tmp ./...
+    cat coverage.out.tmp | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
     go tool cover -func=coverage.out
     popd
 
@@ -97,16 +104,23 @@ coverage() {
 
 	    echo ""
 
-	    target_pct="$(cat ${target_out} |sed -E 's/.*total.*\t([0-9.]+)%/\1/;t;d')"
-	    head_pct="$(cat ${head_out} |sed -E 's/.*total.*\t([0-9.]+)%/\1/;t;d')"
+	    target_pct="$(tail -n2 ${target_out} | head -n1 | sed -E 's/.*total.*\t([0-9.]+)%.*/\1/')"
+	    head_pct="$(tail -n2 ${head_out} | head -n1 | sed -E 's/.*total.*\t([0-9.]+)%/\1/')"
 	    echo "Results: ${target} ${target_pct}% HEAD ${head_pct}%"
 
 	    delta_pct=$(echo "$head_pct - $target_pct" | bc -l)
 	    echo "Delta: ${delta_pct}"
 
 	    if [[ $delta_pct = \-* ]]; then
-		echo "Regression!";
-		return 1
+		    echo "Regression!";
+
+            target_diff="${output_dir}/target.diff.txt"
+            head_diff="${output_dir}/head.diff.txt"
+            cat "${target_out}" | grep -E '^github.com/pelletier/go-toml' | tr -s "\t " | cut -f 2,3 | sort > "${target_diff}"
+            cat "${head_out}" | grep -E '^github.com/pelletier/go-toml' | tr -s "\t " | cut -f 2,3 | sort > "${head_diff}"
+
+            diff --side-by-side --suppress-common-lines "${target_diff}" "${head_diff}"
+		    return 1
 	    fi
 	    return 0
 	    ;;
@@ -118,6 +132,7 @@ coverage() {
 bench() {
     branch="${1}"
     out="${2}"
+    replace="${3}"
     dir="$(mktemp -d)"
 
     stderr "Executing benchmark for ${branch} at ${dir}"
@@ -129,7 +144,14 @@ bench() {
     fi
 
     pushd "$dir"
-    go test -bench=. -count=10 ./... | tee "${out}"
+
+    if [ "${replace}" != "" ]; then
+        find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2|${replace}|g" {} \;
+        go get "${replace}"
+    fi
+
+    export GOMAXPROCS=2
+    nice -n -19 taskset --cpu-list 0,1 go test '-bench=^Benchmark(Un)?[mM]arshal' -count=5 -run=Nothing ./... | tee "${out}"
     popd
 
     if [ "${branch}" != "HEAD" ]; then
@@ -137,19 +159,114 @@ bench() {
     fi
 }
 
+fmktemp() {
+    if mktemp --version|grep GNU >/dev/null; then
+        mktemp --suffix=-$1;
+    else
+        mktemp -t $1;
+    fi
+}
+
+benchstathtml() {
+python3 - $1 <<'EOF'
+import sys
+
+lines = []
+stop = False
+
+with open(sys.argv[1]) as f:
+    for line in f.readlines():
+        line = line.strip()
+        if line == "":
+            stop = True
+        if not stop:
+            lines.append(line.split(','))
+
+results = []
+for line in reversed(lines[1:]):
+    v2 = float(line[1])
+    results.append([
+        line[0].replace("-32", ""),
+        "%.1fx" % (float(line[3])/v2),  # v1
+        "%.1fx" % (float(line[5])/v2),  # bs
+    ])
+# move geomean to the end
+results.append(results[0])
+del results[0]
+
+
+def printtable(data):
+    print("""
+<table>
+    <thead>
+        <tr><th>Benchmark</th><th>go-toml v1</th><th>BurntSushi/toml</th></tr>
+    </thead>
+    <tbody>""")
+
+    for r in data:
+        print("        <tr><td>{}</td><td>{}</td><td>{}</td></tr>".format(*r))
+
+    print("""     </tbody>
+</table>""")
+
+
+def match(x):
+    return "ReferenceFile" in x[0] or "HugoFrontMatter" in x[0]
+
+above = [x for x in results if match(x)]
+below = [x for x in results if not match(x)]
+
+printtable(above)
+print("<details><summary>See more</summary>")
+print("""<p>The table above has the results of the most common use-cases. The table below
+contains the results of all benchmarks, including unrealistic ones. It is
+provided for completeness.</p>""")
+printtable(below)
+print('<p>This table can be generated with <code>./ci.sh benchmark -a -html</code>.</p>')
+print("</details>")
+
+EOF
+}
+
 benchmark() {
     case "$1" in
     -d)
         shift
      	target="${1?Need to provide a target branch argument}"
-        old=`mktemp`
+
+        old=`fmktemp ${target}`
         bench "${target}" "${old}"
 
-        new=`mktemp`
+        new=`fmktemp HEAD`
         bench HEAD "${new}"
+
         benchstat "${old}" "${new}"
         return 0
         ;;
+    -a)
+        shift
+
+        v2stats=`fmktemp go-toml-v2`
+        bench HEAD "${v2stats}" "github.com/pelletier/go-toml/v2"
+        v1stats=`fmktemp go-toml-v1`
+        bench HEAD "${v1stats}" "github.com/pelletier/go-toml"
+        bsstats=`fmktemp bs-toml`
+        bench HEAD "${bsstats}" "github.com/BurntSushi/toml"
+
+        cp "${v2stats}" go-toml-v2.txt
+        cp "${v1stats}" go-toml-v1.txt
+        cp "${bsstats}" bs-toml.txt
+
+        if [ "$1" = "-html" ]; then
+            tmpcsv=`fmktemp csv`
+            benchstat -csv -geomean go-toml-v2.txt go-toml-v1.txt bs-toml.txt > $tmpcsv
+            benchstathtml $tmpcsv
+        else
+            benchstat -geomean go-toml-v2.txt go-toml-v1.txt bs-toml.txt
+        fi
+
+        rm -f go-toml-v2.txt go-toml-v1.txt bs-toml.txt
+        return $?
     esac
 
     bench "${1-HEAD}" `mktemp`
diff --git a/vendor/github.com/pelletier/go-toml/v2/decode.go b/vendor/github.com/pelletier/go-toml/v2/decode.go
index 33ac2a967..4af965360 100644
--- a/vendor/github.com/pelletier/go-toml/v2/decode.go
+++ b/vendor/github.com/pelletier/go-toml/v2/decode.go
@@ -35,26 +35,42 @@ func parseLocalDate(b []byte) (LocalDate, error) {
 		return date, newDecodeError(b, "dates are expected to have the format YYYY-MM-DD")
 	}
 
-	date.Year = parseDecimalDigits(b[0:4])
+	var err error
 
-	v := parseDecimalDigits(b[5:7])
+	date.Year, err = parseDecimalDigits(b[0:4])
+	if err != nil {
+		return LocalDate{}, err
+	}
+
+	date.Month, err = parseDecimalDigits(b[5:7])
+	if err != nil {
+		return LocalDate{}, err
+	}
 
-	date.Month = time.Month(v)
+	date.Day, err = parseDecimalDigits(b[8:10])
+	if err != nil {
+		return LocalDate{}, err
+	}
 
-	date.Day = parseDecimalDigits(b[8:10])
+	if !isValidDate(date.Year, date.Month, date.Day) {
+		return LocalDate{}, newDecodeError(b, "impossible date")
+	}
 
 	return date, nil
 }
 
-func parseDecimalDigits(b []byte) int {
+func parseDecimalDigits(b []byte) (int, error) {
 	v := 0
 
-	for _, c := range b {
+	for i, c := range b {
+		if c < '0' || c > '9' {
+			return 0, newDecodeError(b[i:i+1], "expected digit (0-9)")
+		}
 		v *= 10
 		v += int(c - '0')
 	}
 
-	return v
+	return v, nil
 }
 
 func parseDateTime(b []byte) (time.Time, error) {
@@ -75,7 +91,7 @@ func parseDateTime(b []byte) (time.Time, error) {
 		panic("date time should have a timezone")
 	}
 
-	if b[0] == 'Z' {
+	if b[0] == 'Z' || b[0] == 'z' {
 		b = b[1:]
 		zone = time.UTC
 	} else {
@@ -83,15 +99,42 @@ func parseDateTime(b []byte) (time.Time, error) {
 		if len(b) != dateTimeByteLen {
 			return time.Time{}, newDecodeError(b, "invalid date-time timezone")
 		}
-		direction := 1
-		if b[0] == '-' {
+		var direction int
+		switch b[0] {
+		case '-':
 			direction = -1
+		case '+':
+			direction = +1
+		default:
+			return time.Time{}, newDecodeError(b[:1], "invalid timezone offset character")
+		}
+
+		if b[3] != ':' {
+			return time.Time{}, newDecodeError(b[3:4], "expected a : separator")
+		}
+
+		hours, err := parseDecimalDigits(b[1:3])
+		if err != nil {
+			return time.Time{}, err
+		}
+		if hours > 23 {
+			return time.Time{}, newDecodeError(b[:1], "invalid timezone offset hours")
+		}
+
+		minutes, err := parseDecimalDigits(b[4:6])
+		if err != nil {
+			return time.Time{}, err
+		}
+		if minutes > 59 {
+			return time.Time{}, newDecodeError(b[:1], "invalid timezone offset minutes")
 		}
 
-		hours := digitsToInt(b[1:3])
-		minutes := digitsToInt(b[4:6])
 		seconds := direction * (hours*3600 + minutes*60)
-		zone = time.FixedZone("", seconds)
+		if seconds == 0 {
+			zone = time.UTC
+		} else {
+			zone = time.FixedZone("", seconds)
+		}
 		b = b[dateTimeByteLen:]
 	}
 
@@ -100,13 +143,13 @@ func parseDateTime(b []byte) (time.Time, error) {
 	}
 
 	t := time.Date(
-		dt.Date.Year,
-		dt.Date.Month,
-		dt.Date.Day,
-		dt.Time.Hour,
-		dt.Time.Minute,
-		dt.Time.Second,
-		dt.Time.Nanosecond,
+		dt.Year,
+		time.Month(dt.Month),
+		dt.Day,
+		dt.Hour,
+		dt.Minute,
+		dt.Second,
+		dt.Nanosecond,
 		zone)
 
 	return t, nil
@@ -124,10 +167,10 @@ func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
 	if err != nil {
 		return dt, nil, err
 	}
-	dt.Date = date
+	dt.LocalDate = date
 
 	sep := b[10]
-	if sep != 'T' && sep != ' ' {
+	if sep != 'T' && sep != ' ' && sep != 't' {
 		return dt, nil, newDecodeError(b[10:11], "datetime separator is expected to be T or a space")
 	}
 
@@ -135,7 +178,7 @@ func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
 	if err != nil {
 		return dt, nil, err
 	}
-	dt.Time = t
+	dt.LocalTime = t
 
 	return dt, rest, nil
 }
@@ -149,45 +192,89 @@ func parseLocalTime(b []byte) (LocalTime, []byte, error) {
 		t     LocalTime
 	)
 
+	// check if b matches to have expected format HH:MM:SS[.NNNNNN]
 	const localTimeByteLen = 8
 	if len(b) < localTimeByteLen {
 		return t, nil, newDecodeError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
 	}
 
-	t.Hour = parseDecimalDigits(b[0:2])
+	var err error
+
+	t.Hour, err = parseDecimalDigits(b[0:2])
+	if err != nil {
+		return t, nil, err
+	}
+
+	if t.Hour > 23 {
+		return t, nil, newDecodeError(b[0:2], "hour cannot be greater 23")
+	}
 	if b[2] != ':' {
 		return t, nil, newDecodeError(b[2:3], "expecting colon between hours and minutes")
 	}
 
-	t.Minute = parseDecimalDigits(b[3:5])
+	t.Minute, err = parseDecimalDigits(b[3:5])
+	if err != nil {
+		return t, nil, err
+	}
+	if t.Minute > 59 {
+		return t, nil, newDecodeError(b[3:5], "minutes cannot be greater 59")
+	}
 	if b[5] != ':' {
 		return t, nil, newDecodeError(b[5:6], "expecting colon between minutes and seconds")
 	}
 
-	t.Second = parseDecimalDigits(b[6:8])
+	t.Second, err = parseDecimalDigits(b[6:8])
+	if err != nil {
+		return t, nil, err
+	}
+
+	if t.Second > 60 {
+		return t, nil, newDecodeError(b[6:8], "seconds cannot be greater 60")
+	}
+
+	b = b[8:]
 
-	const minLengthWithFrac = 9
-	if len(b) >= minLengthWithFrac && b[minLengthWithFrac-1] == '.' {
+	if len(b) >= 1 && b[0] == '.' {
 		frac := 0
+		precision := 0
 		digits := 0
 
-		for i, c := range b[minLengthWithFrac:] {
+		for i, c := range b[1:] {
+			if !isDigit(c) {
+				if i == 0 {
+					return t, nil, newDecodeError(b[0:1], "need at least one digit after fraction point")
+				}
+				break
+			}
+			digits++
+
 			const maxFracPrecision = 9
 			if i >= maxFracPrecision {
-				return t, nil, newDecodeError(b[i:i+1], "maximum precision for date time is nanosecond")
+				// go-toml allows decoding fractional seconds
+				// beyond the supported precision of 9
+				// digits. It truncates the fractional component
+				// to the supported precision and ignores the
+				// remaining digits.
+				//
+				// https://github.com/pelletier/go-toml/discussions/707
+				continue
 			}
 
 			frac *= 10
 			frac += int(c - '0')
-			digits++
+			precision++
 		}
 
-		t.Nanosecond = frac * nspow[digits]
+		if precision == 0 {
+			return t, nil, newDecodeError(b[:1], "nanoseconds need at least one digit")
+		}
 
-		return t, b[9+digits:], nil
-	}
+		t.Nanosecond = frac * nspow[precision]
+		t.Precision = precision
 
-	return t, b[8:], nil
+		return t, b[1+digits:], nil
+	}
+	return t, b, nil
 }
 
 //nolint:cyclop
@@ -196,7 +283,7 @@ func parseFloat(b []byte) (float64, error) {
 		return math.NaN(), nil
 	}
 
-	cleaned, err := checkAndRemoveUnderscores(b)
+	cleaned, err := checkAndRemoveUnderscoresFloats(b)
 	if err != nil {
 		return 0, err
 	}
@@ -209,6 +296,30 @@ func parseFloat(b []byte) (float64, error) {
 		return 0, newDecodeError(b, "float cannot end with a dot")
 	}
 
+	dotAlreadySeen := false
+	for i, c := range cleaned {
+		if c == '.' {
+			if dotAlreadySeen {
+				return 0, newDecodeError(b[i:i+1], "float can have at most one decimal point")
+			}
+			if !isDigit(cleaned[i-1]) {
+				return 0, newDecodeError(b[i-1:i+1], "float decimal point must be preceded by a digit")
+			}
+			if !isDigit(cleaned[i+1]) {
+				return 0, newDecodeError(b[i:i+2], "float decimal point must be followed by a digit")
+			}
+			dotAlreadySeen = true
+		}
+	}
+
+	start := 0
+	if cleaned[0] == '+' || cleaned[0] == '-' {
+		start = 1
+	}
+	if cleaned[start] == '0' && isDigit(cleaned[start+1]) {
+		return 0, newDecodeError(b, "float integer part cannot have leading zeroes")
+	}
+
 	f, err := strconv.ParseFloat(string(cleaned), 64)
 	if err != nil {
 		return 0, newDecodeError(b, "unable to parse float: %w", err)
@@ -218,7 +329,7 @@ func parseFloat(b []byte) (float64, error) {
 }
 
 func parseIntHex(b []byte) (int64, error) {
-	cleaned, err := checkAndRemoveUnderscores(b[2:])
+	cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
 	if err != nil {
 		return 0, err
 	}
@@ -232,7 +343,7 @@ func parseIntHex(b []byte) (int64, error) {
 }
 
 func parseIntOct(b []byte) (int64, error) {
-	cleaned, err := checkAndRemoveUnderscores(b[2:])
+	cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
 	if err != nil {
 		return 0, err
 	}
@@ -246,7 +357,7 @@ func parseIntOct(b []byte) (int64, error) {
 }
 
 func parseIntBin(b []byte) (int64, error) {
-	cleaned, err := checkAndRemoveUnderscores(b[2:])
+	cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
 	if err != nil {
 		return 0, err
 	}
@@ -259,12 +370,26 @@ func parseIntBin(b []byte) (int64, error) {
 	return i, nil
 }
 
+func isSign(b byte) bool {
+	return b == '+' || b == '-'
+}
+
 func parseIntDec(b []byte) (int64, error) {
-	cleaned, err := checkAndRemoveUnderscores(b)
+	cleaned, err := checkAndRemoveUnderscoresIntegers(b)
 	if err != nil {
 		return 0, err
 	}
 
+	startIdx := 0
+
+	if isSign(cleaned[0]) {
+		startIdx++
+	}
+
+	if len(cleaned) > startIdx+1 && cleaned[startIdx] == '0' {
+		return 0, newDecodeError(b, "leading zero not allowed on decimal number")
+	}
+
 	i, err := strconv.ParseInt(string(cleaned), 10, 64)
 	if err != nil {
 		return 0, newDecodeError(b, "couldn't parse decimal number: %w", err)
@@ -273,9 +398,18 @@ func parseIntDec(b []byte) (int64, error) {
 	return i, nil
 }
 
-func checkAndRemoveUnderscores(b []byte) ([]byte, error) {
-	if b[0] == '_' {
-		return nil, newDecodeError(b[0:1], "number cannot start with underscore")
+func checkAndRemoveUnderscoresIntegers(b []byte) ([]byte, error) {
+	start := 0
+	if b[start] == '+' || b[start] == '-' {
+		start++
+	}
+
+	if len(b) == start {
+		return b, nil
+	}
+
+	if b[start] == '_' {
+		return nil, newDecodeError(b[start:start+1], "number cannot start with underscore")
 	}
 
 	if b[len(b)-1] == '_' {
@@ -312,3 +446,99 @@ func checkAndRemoveUnderscores(b []byte) ([]byte, error) {
 
 	return cleaned, nil
 }
+
+func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) {
+	if b[0] == '_' {
+		return nil, newDecodeError(b[0:1], "number cannot start with underscore")
+	}
+
+	if b[len(b)-1] == '_' {
+		return nil, newDecodeError(b[len(b)-1:], "number cannot end with underscore")
+	}
+
+	// fast path
+	i := 0
+	for ; i < len(b); i++ {
+		if b[i] == '_' {
+			break
+		}
+	}
+	if i == len(b) {
+		return b, nil
+	}
+
+	before := false
+	cleaned := make([]byte, 0, len(b))
+
+	for i := 0; i < len(b); i++ {
+		c := b[i]
+
+		switch c {
+		case '_':
+			if !before {
+				return nil, newDecodeError(b[i-1:i+1], "number must have at least one digit between underscores")
+			}
+			if i < len(b)-1 && (b[i+1] == 'e' || b[i+1] == 'E') {
+				return nil, newDecodeError(b[i+1:i+2], "cannot have underscore before exponent")
+			}
+			before = false
+		case '+', '-':
+			// signed exponents
+			cleaned = append(cleaned, c)
+			before = false
+		case 'e', 'E':
+			if i < len(b)-1 && b[i+1] == '_' {
+				return nil, newDecodeError(b[i+1:i+2], "cannot have underscore after exponent")
+			}
+			cleaned = append(cleaned, c)
+		case '.':
+			if i < len(b)-1 && b[i+1] == '_' {
+				return nil, newDecodeError(b[i+1:i+2], "cannot have underscore after decimal point")
+			}
+			if i > 0 && b[i-1] == '_' {
+				return nil, newDecodeError(b[i-1:i], "cannot have underscore before decimal point")
+			}
+			cleaned = append(cleaned, c)
+		default:
+			before = true
+			cleaned = append(cleaned, c)
+		}
+	}
+
+	return cleaned, nil
+}
+
+// isValidDate checks if a provided date is a date that exists.
+func isValidDate(year int, month int, day int) bool {
+	return month > 0 && month < 13 && day > 0 && day <= daysIn(month, year)
+}
+
+// daysBefore[m] counts the number of days in a non-leap year
+// before month m begins. There is an entry for m=12, counting
+// the number of days before January of next year (365).
+var daysBefore = [...]int32{
+	0,
+	31,
+	31 + 28,
+	31 + 28 + 31,
+	31 + 28 + 31 + 30,
+	31 + 28 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30,
+	31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31,
+}
+
+func daysIn(m int, year int) int {
+	if m == 2 && isLeap(year) {
+		return 29
+	}
+	return int(daysBefore[m] - daysBefore[m-1])
+}
+
+func isLeap(year int) bool {
+	return year%4 == 0 && (year%100 != 0 || year%400 == 0)
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/errors.go b/vendor/github.com/pelletier/go-toml/v2/errors.go
index 712765bba..2e7f0ffdf 100644
--- a/vendor/github.com/pelletier/go-toml/v2/errors.go
+++ b/vendor/github.com/pelletier/go-toml/v2/errors.go
@@ -5,7 +5,7 @@ import (
 	"strconv"
 	"strings"
 
-	"github.com/pelletier/go-toml/v2/internal/unsafe"
+	"github.com/pelletier/go-toml/v2/internal/danger"
 )
 
 // DecodeError represents an error encountered during the parsing or decoding
@@ -27,7 +27,7 @@ type DecodeError struct {
 // corresponding field in the target value. It contains all the missing fields
 // in Errors.
 //
-// Emitted by Decoder when SetStrict(true) was called.
+// Emitted by Decoder when DisallowUnknownFields() was called.
 type StrictMissingError struct {
 	// One error per field that could not be found.
 	Errors []DecodeError
@@ -103,9 +103,10 @@ func (e *DecodeError) Key() Key {
 //
 // The function copies all bytes used in DecodeError, so that document and
 // highlight can be freely deallocated.
+//
 //nolint:funlen
 func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
-	offset := unsafe.SubsliceOffset(document, de.highlight)
+	offset := danger.SubsliceOffset(document, de.highlight)
 
 	errMessage := de.Error()
 	errLine, errColumn := positionAtEnd(document[:offset])
@@ -116,6 +117,7 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
 	maxLine := errLine + len(after) - 1
 	lineColumnWidth := len(strconv.Itoa(maxLine))
 
+	// Write the lines of context strictly before the error.
 	for i := len(before) - 1; i > 0; i-- {
 		line := errLine - i
 		buf.WriteString(formatLineNumber(line, lineColumnWidth))
@@ -129,6 +131,8 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
 		buf.WriteRune('\n')
 	}
 
+	// Write the document line that contains the error.
+
 	buf.WriteString(formatLineNumber(errLine, lineColumnWidth))
 	buf.WriteString("| ")
 
@@ -143,6 +147,10 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
 	}
 
 	buf.WriteRune('\n')
+
+	// Write the line with the error message itself (so it does not have a line
+	// number).
+
 	buf.WriteString(strings.Repeat(" ", lineColumnWidth))
 	buf.WriteString("| ")
 
@@ -157,6 +165,8 @@ func wrapDecodeError(document []byte, de *decodeError) *DecodeError {
 		buf.WriteString(errMessage)
 	}
 
+	// Write the lines of context strictly after the error.
+
 	for i := 1; i < len(after); i++ {
 		buf.WriteRune('\n')
 		line := errLine + i
@@ -230,7 +240,7 @@ forward:
 			rest = rest[o+1:]
 			o = 0
 
-		case o == len(rest)-1 && o > 0:
+		case o == len(rest)-1:
 			// add last line only if it's non-empty
 			afterLines = append(afterLines, rest)
 
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go b/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go
index ba2729e05..9dec2e000 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/ast/ast.go
@@ -2,23 +2,26 @@ package ast
 
 import (
 	"fmt"
+	"unsafe"
+
+	"github.com/pelletier/go-toml/v2/internal/danger"
 )
 
 // Iterator starts uninitialized, you need to call Next() first.
 //
 // For example:
 //
-// it := n.Children()
-// for it.Next() {
-// 		it.Node()
-// }
+//	it := n.Children()
+//	for it.Next() {
+//			it.Node()
+//	}
 type Iterator struct {
 	started bool
-	node    Node
+	node    *Node
 }
 
-// Next moves the iterator forward and returns true if points to a node, false
-// otherwise.
+// Next moves the iterator forward and returns true if points to a
+// node, false otherwise.
 func (c *Iterator) Next() bool {
 	if !c.started {
 		c.started = true
@@ -28,8 +31,14 @@ func (c *Iterator) Next() bool {
 	return c.node.Valid()
 }
 
+// IsLast returns true if the current node of the iterator is the last
+// one.  Subsequent call to Next() will return false.
+func (c *Iterator) IsLast() bool {
+	return c.node.next == 0
+}
+
 // Node returns a copy of the node pointed at by the iterator.
-func (c *Iterator) Node() Node {
+func (c *Iterator) Node() *Node {
 	return c.node
 }
 
@@ -44,65 +53,69 @@ type Root struct {
 func (r *Root) Iterator() Iterator {
 	it := Iterator{}
 	if len(r.nodes) > 0 {
-		it.node = r.nodes[0]
+		it.node = &r.nodes[0]
 	}
 	return it
 }
 
-func (r *Root) at(idx int) Node {
-	// TODO: unsafe to point to the node directly
-	return r.nodes[idx]
+func (r *Root) at(idx Reference) *Node {
+	return &r.nodes[idx]
 }
 
-// Arrays have one child per element in the array.
-// InlineTables have one child per key-value pair in the table.
-// KeyValues have at least two children. The first one is the value. The
-// rest make a potentially dotted key.
-// Table and Array table have one child per element of the key they
-// represent (same as KeyValue, but without the last node being the value).
-// children []Node
+// Arrays have one child per element in the array.  InlineTables have
+// one child per key-value pair in the table.  KeyValues have at least
+// two children. The first one is the value. The rest make a
+// potentially dotted key.  Table and Array table have one child per
+// element of the key they represent (same as KeyValue, but without
+// the last node being the value).
 type Node struct {
 	Kind Kind
-	Data []byte // Raw bytes from the input
-
-	// next idx (in the root array). 0 if last of the collection.
-	next int
-	// child idx (in the root array). 0 if no child.
-	child int
-	// pointer to the root array
-	root *Root
+	Raw  Range  // Raw bytes from the input.
+	Data []byte // Node value (either allocated or referencing the input).
+
+	// References to other nodes, as offsets in the backing array
+	// from this node. References can go backward, so those can be
+	// negative.
+	next  int // 0 if last element
+	child int // 0 if no child
+}
+
+type Range struct {
+	Offset uint32
+	Length uint32
 }
 
-// Next returns a copy of the next node, or an invalid Node if there is no
-// next node.
-func (n Node) Next() Node {
-	if n.next <= 0 {
-		return noNode
+// Next returns a copy of the next node, or an invalid Node if there
+// is no next node.
+func (n *Node) Next() *Node {
+	if n.next == 0 {
+		return nil
 	}
-	return n.root.at(n.next)
+	ptr := unsafe.Pointer(n)
+	size := unsafe.Sizeof(Node{})
+	return (*Node)(danger.Stride(ptr, size, n.next))
 }
 
-// Child returns a copy of the first child node of this node. Other children
-// can be accessed calling Next on the first child.
-// Returns an invalid Node if there is none.
-func (n Node) Child() Node {
-	if n.child <= 0 {
-		return noNode
+// Child returns a copy of the first child node of this node. Other
+// children can be accessed calling Next on the first child.  Returns
+// an invalid Node if there is none.
+func (n *Node) Child() *Node {
+	if n.child == 0 {
+		return nil
 	}
-	return n.root.at(n.child)
+	ptr := unsafe.Pointer(n)
+	size := unsafe.Sizeof(Node{})
+	return (*Node)(danger.Stride(ptr, size, n.child))
 }
 
 // Valid returns true if the node's kind is set (not to Invalid).
-func (n Node) Valid() bool {
-	return n.Kind != Invalid
+func (n *Node) Valid() bool {
+	return n != nil
 }
 
-var noNode = Node{}
-
-// Key returns the child nodes making the Key on a supported node. Panics
-// otherwise.
-// They are guaranteed to be all be of the Kind Key. A simple key would return
-// just one element.
+// Key returns the child nodes making the Key on a supported
+// node. Panics otherwise.  They are guaranteed to be all be of the
+// Kind Key. A simple key would return just one element.
 func (n *Node) Key() Iterator {
 	switch n.Kind {
 	case KeyValue:
@@ -119,20 +132,13 @@ func (n *Node) Key() Iterator {
 }
 
 // Value returns a pointer to the value node of a KeyValue.
-// Guaranteed to be non-nil.
-// Panics if not called on a KeyValue node, or if the Children are malformed.
-func (n Node) Value() Node {
-	assertKind(KeyValue, n)
+// Guaranteed to be non-nil.  Panics if not called on a KeyValue node,
+// or if the Children are malformed.
+func (n *Node) Value() *Node {
 	return n.Child()
 }
 
 // Children returns an iterator over a node's children.
-func (n Node) Children() Iterator {
+func (n *Node) Children() Iterator {
 	return Iterator{node: n.Child()}
 }
-
-func assertKind(k Kind, n Node) {
-	if n.Kind != k {
-		panic(fmt.Errorf("method was expecting a %s, not a %s", k, n.Kind))
-	}
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go b/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go
index 796b7f1d9..120f16e5c 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/ast/builder.go
@@ -1,12 +1,11 @@
 package ast
 
-type Reference struct {
-	idx int
-	set bool
-}
+type Reference int
+
+const InvalidReference Reference = -1
 
 func (r Reference) Valid() bool {
-	return r.set
+	return r != InvalidReference
 }
 
 type Builder struct {
@@ -18,8 +17,8 @@ func (b *Builder) Tree() *Root {
 	return &b.tree
 }
 
-func (b *Builder) NodeAt(ref Reference) Node {
-	return b.tree.at(ref.idx)
+func (b *Builder) NodeAt(ref Reference) *Node {
+	return b.tree.at(ref)
 }
 
 func (b *Builder) Reset() {
@@ -28,33 +27,25 @@ func (b *Builder) Reset() {
 }
 
 func (b *Builder) Push(n Node) Reference {
-	n.root = &b.tree
 	b.lastIdx = len(b.tree.nodes)
 	b.tree.nodes = append(b.tree.nodes, n)
-	return Reference{
-		idx: b.lastIdx,
-		set: true,
-	}
+	return Reference(b.lastIdx)
 }
 
 func (b *Builder) PushAndChain(n Node) Reference {
-	n.root = &b.tree
 	newIdx := len(b.tree.nodes)
 	b.tree.nodes = append(b.tree.nodes, n)
 	if b.lastIdx >= 0 {
-		b.tree.nodes[b.lastIdx].next = newIdx
+		b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx
 	}
 	b.lastIdx = newIdx
-	return Reference{
-		idx: b.lastIdx,
-		set: true,
-	}
+	return Reference(b.lastIdx)
 }
 
 func (b *Builder) AttachChild(parent Reference, child Reference) {
-	b.tree.nodes[parent.idx].child = child.idx
+	b.tree.nodes[parent].child = int(child) - int(parent)
 }
 
 func (b *Builder) Chain(from Reference, to Reference) {
-	b.tree.nodes[from.idx].next = to.idx
+	b.tree.nodes[from].next = int(to) - int(from)
 }
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go b/vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go
index bcf6c91c1..2b50c67fc 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/ast/kind.go
@@ -25,9 +25,9 @@ const (
 	Float
 	Integer
 	LocalDate
+	LocalTime
 	LocalDateTime
 	DateTime
-	Time
 )
 
 func (k Kind) String() string {
@@ -58,12 +58,12 @@ func (k Kind) String() string {
 		return "Integer"
 	case LocalDate:
 		return "LocalDate"
+	case LocalTime:
+		return "LocalTime"
 	case LocalDateTime:
 		return "LocalDateTime"
 	case DateTime:
 		return "DateTime"
-	case Time:
-		return "Time"
 	}
 	panic(fmt.Errorf("Kind.String() not implemented for '%d'", k))
 }
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/unsafe/unsafe.go b/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
similarity index 84%
rename from vendor/github.com/pelletier/go-toml/v2/internal/unsafe/unsafe.go
rename to vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
index 742c6ab27..e38e1131b 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/unsafe/unsafe.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
@@ -1,4 +1,4 @@
-package unsafe
+package danger
 
 import (
 	"fmt"
@@ -57,3 +57,9 @@ func BytesRange(start []byte, end []byte) []byte {
 
 	return start[:l]
 }
+
+func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer {
+	// TODO: replace with unsafe.Add when Go 1.17 is released
+	//   https://github.com/golang/go/issues/40481
+	return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset))
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go b/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
new file mode 100644
index 000000000..9d41c28a2
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
@@ -0,0 +1,23 @@
+package danger
+
+import (
+	"reflect"
+	"unsafe"
+)
+
+// typeID is used as key in encoder and decoder caches to enable using
+// the optimize runtime.mapaccess2_fast64 function instead of the more
+// expensive lookup if we were to use reflect.Type as map key.
+//
+// typeID holds the pointer to the reflect.Type value, which is unique
+// in the program.
+//
+// https://github.com/segmentio/encoding/blob/master/json/codec.go#L59-L61
+type TypeID unsafe.Pointer
+
+func MakeTypeID(t reflect.Type) TypeID {
+	// reflect.Type has the fields:
+	// typ unsafe.Pointer
+	// ptr unsafe.Pointer
+	return TypeID((*[2]unsafe.Pointer)(unsafe.Pointer(&t))[1])
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
index be99f7206..7c148f48d 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
@@ -11,19 +11,19 @@ type KeyTracker struct {
 }
 
 // UpdateTable sets the state of the tracker with the AST table node.
-func (t *KeyTracker) UpdateTable(node ast.Node) {
+func (t *KeyTracker) UpdateTable(node *ast.Node) {
 	t.reset()
 	t.Push(node)
 }
 
 // UpdateArrayTable sets the state of the tracker with the AST array table node.
-func (t *KeyTracker) UpdateArrayTable(node ast.Node) {
+func (t *KeyTracker) UpdateArrayTable(node *ast.Node) {
 	t.reset()
 	t.Push(node)
 }
 
 // Push the given key on the stack.
-func (t *KeyTracker) Push(node ast.Node) {
+func (t *KeyTracker) Push(node *ast.Node) {
 	it := node.Key()
 	for it.Next() {
 		t.k = append(t.k, string(it.Node().Data))
@@ -31,7 +31,7 @@ func (t *KeyTracker) Push(node ast.Node) {
 }
 
 // Pop key from stack.
-func (t *KeyTracker) Pop(node ast.Node) {
+func (t *KeyTracker) Pop(node *ast.Node) {
 	it := node.Key()
 	for it.Next() {
 		t.k = t.k[:len(t.k)-1]
diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
index e245aace2..a7ee05ba6 100644
--- a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
+++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
@@ -1,7 +1,9 @@
 package tracker
 
 import (
+	"bytes"
 	"fmt"
+	"sync"
 
 	"github.com/pelletier/go-toml/v2/internal/ast"
 )
@@ -29,67 +31,132 @@ func (k keyKind) String() string {
 	panic("missing keyKind string mapping")
 }
 
-// SeenTracker tracks which keys have been seen with which TOML type to flag duplicates
-// and mismatches according to the spec.
+// SeenTracker tracks which keys have been seen with which TOML type to flag
+// duplicates and mismatches according to the spec.
+//
+// Each node in the visited tree is represented by an entry. Each entry has an
+// identifier, which is provided by a counter. Entries are stored in the array
+// entries. As new nodes are discovered (referenced for the first time in the
+// TOML document), entries are created and appended to the array. An entry
+// points to its parent using its id.
+//
+// To find whether a given key (sequence of []byte) has already been visited,
+// the entries are linearly searched, looking for one with the right name and
+// parent id.
+//
+// Given that all keys appear in the document after their parent, it is
+// guaranteed that all descendants of a node are stored after the node, this
+// speeds up the search process.
+//
+// When encountering [[array tables]], the descendants of that node are removed
+// to allow that branch of the tree to be "rediscovered". To maintain the
+// invariant above, the deletion process needs to keep the order of entries.
+// This results in more copies in that case.
 type SeenTracker struct {
-	root    *info
-	current *info
+	entries    []entry
+	currentIdx int
 }
 
-type info struct {
-	parent   *info
-	kind     keyKind
-	children map[string]*info
-	explicit bool
-}
+var pool sync.Pool
 
-func (i *info) Clear() {
-	i.children = nil
+func (s *SeenTracker) reset() {
+	// Always contains a root element at index 0.
+	s.currentIdx = 0
+	if len(s.entries) == 0 {
+		s.entries = make([]entry, 1, 2)
+	} else {
+		s.entries = s.entries[:1]
+	}
+	s.entries[0].child = -1
+	s.entries[0].next = -1
 }
 
-func (i *info) Has(k string) (*info, bool) {
-	c, ok := i.children[k]
-	return c, ok
-}
+type entry struct {
+	// Use -1 to indicate no child or no sibling.
+	child int
+	next  int
 
-func (i *info) SetKind(kind keyKind) {
-	i.kind = kind
+	name     []byte
+	kind     keyKind
+	explicit bool
+	kv       bool
 }
 
-func (i *info) CreateTable(k string, explicit bool) *info {
-	return i.createChild(k, tableKind, explicit)
+// Find the index of the child of parentIdx with key k. Returns -1 if
+// it does not exist.
+func (s *SeenTracker) find(parentIdx int, k []byte) int {
+	for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
+		if bytes.Equal(s.entries[i].name, k) {
+			return i
+		}
+	}
+	return -1
 }
 
-func (i *info) CreateArrayTable(k string, explicit bool) *info {
-	return i.createChild(k, arrayTableKind, explicit)
-}
+// Remove all descendants of node at position idx.
+func (s *SeenTracker) clear(idx int) {
+	if idx >= len(s.entries) {
+		return
+	}
 
-func (i *info) createChild(k string, kind keyKind, explicit bool) *info {
-	if i.children == nil {
-		i.children = make(map[string]*info, 1)
+	for i := s.entries[idx].child; i >= 0; {
+		next := s.entries[i].next
+		n := s.entries[0].next
+		s.entries[0].next = i
+		s.entries[i].next = n
+		s.entries[i].name = nil
+		s.clear(i)
+		i = next
 	}
 
-	x := &info{
-		parent:   i,
+	s.entries[idx].child = -1
+}
+
+func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool, kv bool) int {
+	e := entry{
+		child: -1,
+		next:  s.entries[parentIdx].child,
+
+		name:     name,
 		kind:     kind,
 		explicit: explicit,
+		kv:       kv,
+	}
+	var idx int
+	if s.entries[0].next >= 0 {
+		idx = s.entries[0].next
+		s.entries[0].next = s.entries[idx].next
+		s.entries[idx] = e
+	} else {
+		idx = len(s.entries)
+		s.entries = append(s.entries, e)
 	}
-	i.children[k] = x
-	return x
+
+	s.entries[parentIdx].child = idx
+
+	return idx
 }
 
-// CheckExpression takes a top-level node and checks that it does not contain keys
-// that have been seen in previous calls, and validates that types are consistent.
-func (s *SeenTracker) CheckExpression(node ast.Node) error {
-	if s.root == nil {
-		s.root = &info{
-			kind: tableKind,
+func (s *SeenTracker) setExplicitFlag(parentIdx int) {
+	for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next {
+		if s.entries[i].kv {
+			s.entries[i].explicit = true
+			s.entries[i].kv = false
 		}
-		s.current = s.root
+		s.setExplicitFlag(i)
+	}
+}
+
+// CheckExpression takes a top-level node and checks that it does not contain
+// keys that have been seen in previous calls, and validates that types are
+// consistent.
+func (s *SeenTracker) CheckExpression(node *ast.Node) error {
+	if s.entries == nil {
+		s.reset()
 	}
 	switch node.Kind {
 	case ast.KeyValue:
-		return s.checkKeyValue(s.current, node)
+		return s.checkKeyValue(node)
 	case ast.Table:
 		return s.checkTable(node)
 	case ast.ArrayTable:
@@ -97,104 +164,193 @@ func (s *SeenTracker) CheckExpression(node ast.Node) error {
 	default:
 		panic(fmt.Errorf("this should not be a top level node type: %s", node.Kind))
 	}
-
 }
-func (s *SeenTracker) checkTable(node ast.Node) error {
-	s.current = s.root
+
+func (s *SeenTracker) checkTable(node *ast.Node) error {
+	if s.currentIdx >= 0 {
+		s.setExplicitFlag(s.currentIdx)
+	}
 
 	it := node.Key()
-	// handle the first parts of the key, excluding the last one
+
+	parentIdx := 0
+
+	// This code is duplicated in checkArrayTable. This is because factoring
+	// it in a function requires to copy the iterator, or allocate it to the
+	// heap, which is not cheap.
 	for it.Next() {
-		if !it.Node().Next().Valid() {
+		if it.IsLast() {
 			break
 		}
 
-		k := string(it.Node().Data)
-		child, found := s.current.Has(k)
-		if !found {
-			child = s.current.CreateTable(k, false)
+		k := it.Node().Data
+
+		idx := s.find(parentIdx, k)
+
+		if idx < 0 {
+			idx = s.create(parentIdx, k, tableKind, false, false)
+		} else {
+			entry := s.entries[idx]
+			if entry.kind == valueKind {
+				return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
+			}
 		}
-		s.current = child
+		parentIdx = idx
 	}
 
-	// handle the last part of the key
-	k := string(it.Node().Data)
+	k := it.Node().Data
+	idx := s.find(parentIdx, k)
 
-	i, found := s.current.Has(k)
-	if found {
-		if i.kind != tableKind {
-			return fmt.Errorf("toml: key %s should be a table, not a %s", k, i.kind)
+	if idx >= 0 {
+		kind := s.entries[idx].kind
+		if kind != tableKind {
+			return fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind)
 		}
-		if i.explicit {
-			return fmt.Errorf("toml: table %s already exists", k)
+		if s.entries[idx].explicit {
+			return fmt.Errorf("toml: table %s already exists", string(k))
 		}
-		i.explicit = true
-		s.current = i
+		s.entries[idx].explicit = true
 	} else {
-		s.current = s.current.CreateTable(k, true)
+		idx = s.create(parentIdx, k, tableKind, true, false)
 	}
 
+	s.currentIdx = idx
+
 	return nil
 }
 
-func (s *SeenTracker) checkArrayTable(node ast.Node) error {
-	s.current = s.root
+func (s *SeenTracker) checkArrayTable(node *ast.Node) error {
+	if s.currentIdx >= 0 {
+		s.setExplicitFlag(s.currentIdx)
+	}
 
 	it := node.Key()
 
-	// handle the first parts of the key, excluding the last one
+	parentIdx := 0
+
 	for it.Next() {
-		if !it.Node().Next().Valid() {
+		if it.IsLast() {
 			break
 		}
 
-		k := string(it.Node().Data)
-		child, found := s.current.Has(k)
-		if !found {
-			child = s.current.CreateTable(k, false)
+		k := it.Node().Data
+
+		idx := s.find(parentIdx, k)
+
+		if idx < 0 {
+			idx = s.create(parentIdx, k, tableKind, false, false)
+		} else {
+			entry := s.entries[idx]
+			if entry.kind == valueKind {
+				return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
+			}
 		}
-		s.current = child
+
+		parentIdx = idx
 	}
 
-	// handle the last part of the key
-	k := string(it.Node().Data)
+	k := it.Node().Data
+	idx := s.find(parentIdx, k)
 
-	info, found := s.current.Has(k)
-	if found {
-		if info.kind != arrayTableKind {
-			return fmt.Errorf("toml: key %s already exists as a %s,  but should be an array table", info.kind, k)
+	if idx >= 0 {
+		kind := s.entries[idx].kind
+		if kind != arrayTableKind {
+			return fmt.Errorf("toml: key %s already exists as a %s,  but should be an array table", kind, string(k))
 		}
-		info.Clear()
+		s.clear(idx)
 	} else {
-		info = s.current.CreateArrayTable(k, true)
+		idx = s.create(parentIdx, k, arrayTableKind, true, false)
 	}
 
-	s.current = info
+	s.currentIdx = idx
+
 	return nil
 }
 
-func (s *SeenTracker) checkKeyValue(context *info, node ast.Node) error {
+func (s *SeenTracker) checkKeyValue(node *ast.Node) error {
+	parentIdx := s.currentIdx
 	it := node.Key()
 
-	// handle the first parts of the key, excluding the last one
 	for it.Next() {
-		k := string(it.Node().Data)
-		child, found := context.Has(k)
-		if found {
-			if child.kind != tableKind {
-				return fmt.Errorf("toml: expected %s to be a table, not a %s", k, child.kind)
-			}
+		k := it.Node().Data
+
+		idx := s.find(parentIdx, k)
+
+		if idx < 0 {
+			idx = s.create(parentIdx, k, tableKind, false, true)
 		} else {
-			child = context.CreateTable(k, false)
+			entry := s.entries[idx]
+			if it.IsLast() {
+				return fmt.Errorf("toml: key %s is already defined", string(k))
+			} else if entry.kind != tableKind {
+				return fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind)
+			} else if entry.explicit {
+				return fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k))
+			}
 		}
-		context = child
+
+		parentIdx = idx
 	}
 
-	if node.Value().Kind == ast.InlineTable {
-		context.SetKind(tableKind)
-	} else {
-		context.SetKind(valueKind)
+	s.entries[parentIdx].kind = valueKind
+
+	value := node.Value()
+
+	switch value.Kind {
+	case ast.InlineTable:
+		return s.checkInlineTable(value)
+	case ast.Array:
+		return s.checkArray(value)
+	}
+
+	return nil
+}
+
+func (s *SeenTracker) checkArray(node *ast.Node) error {
+	it := node.Children()
+	for it.Next() {
+		n := it.Node()
+		switch n.Kind {
+		case ast.InlineTable:
+			err := s.checkInlineTable(n)
+			if err != nil {
+				return err
+			}
+		case ast.Array:
+			err := s.checkArray(n)
+			if err != nil {
+				return err
+			}
+		}
+	}
+	return nil
+}
+
+func (s *SeenTracker) checkInlineTable(node *ast.Node) error {
+	if pool.New == nil {
+		pool.New = func() interface{} {
+			return &SeenTracker{}
+		}
+	}
+
+	s = pool.Get().(*SeenTracker)
+	s.reset()
+
+	it := node.Children()
+	for it.Next() {
+		n := it.Node()
+		err := s.checkKeyValue(n)
+		if err != nil {
+			return err
+		}
 	}
 
+	// As inline tables are self-contained, the tracker does not
+	// need to retain the details of what they contain. The
+	// keyValue element that creates the inline table is kept to
+	// mark the presence of the inline table and prevent
+	// redefinition of its keys: check* functions cannot walk into
+	// a value.
+	pool.Put(s)
 	return nil
 }
diff --git a/vendor/github.com/pelletier/go-toml/v2/localtime.go b/vendor/github.com/pelletier/go-toml/v2/localtime.go
index a947044ac..30a31dcbd 100644
--- a/vendor/github.com/pelletier/go-toml/v2/localtime.go
+++ b/vendor/github.com/pelletier/go-toml/v2/localtime.go
@@ -1,300 +1,120 @@
-// Implementation of TOML's local date/time.
-// Copied over from https://github.com/googleapis/google-cloud-go/blob/master/civil/civil.go
-// to avoid pulling all the Google dependencies.
-//
-// Copyright 2016 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//      http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-// Package civil implements types for civil time, a time-zone-independent
-// representation of time that follows the rules of the proleptic
-// Gregorian calendar with exactly 24-hour days, 60-minute hours, and 60-second
-// minutes.
-//
-// Because they lack location information, these types do not represent unique
-// moments or intervals of time. Use time.Time for that purpose.
-
 package toml
 
 import (
 	"fmt"
+	"strings"
 	"time"
 )
 
-// A LocalDate represents a date (year, month, day).
-//
-// This type does not include location information, and therefore does not
-// describe a unique 24-hour timespan.
+// LocalDate represents a calendar day in no specific timezone.
 type LocalDate struct {
-	Year  int        // Year (e.g., 2014).
-	Month time.Month // Month of the year (January = 1, ...).
-	Day   int        // Day of the month, starting at 1.
-}
-
-// LocalDateOf returns the LocalDate in which a time occurs in that time's location.
-func LocalDateOf(t time.Time) LocalDate {
-	var d LocalDate
-	d.Year, d.Month, d.Day = t.Date()
-
-	return d
+	Year  int
+	Month int
+	Day   int
 }
 
-// ParseLocalDate parses a string in RFC3339 full-date format and returns the date value it represents.
-func ParseLocalDate(s string) (LocalDate, error) {
-	t, err := time.Parse("2006-01-02", s)
-	if err != nil {
-		return LocalDate{}, err
-	}
-
-	return LocalDateOf(t), nil
+// AsTime converts d into a specific time instance at midnight in zone.
+func (d LocalDate) AsTime(zone *time.Location) time.Time {
+	return time.Date(d.Year, time.Month(d.Month), d.Day, 0, 0, 0, 0, zone)
 }
 
-// String returns the date in RFC3339 full-date format.
+// String returns RFC 3339 representation of d.
 func (d LocalDate) String() string {
 	return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day)
 }
 
-// IsValid reports whether the date is valid.
-func (d LocalDate) IsValid() bool {
-	return LocalDateOf(d.In(time.UTC)) == d
-}
-
-// In returns the time corresponding to time 00:00:00 of the date in the location.
-//
-// In is always consistent with time.LocalDate, even when time.LocalDate returns a time
-// on a different day. For example, if loc is America/Indiana/Vincennes, then both
-//     time.LocalDate(1955, time.May, 1, 0, 0, 0, 0, loc)
-// and
-//     civil.LocalDate{Year: 1955, Month: time.May, Day: 1}.In(loc)
-// return 23:00:00 on April 30, 1955.
-//
-// In panics if loc is nil.
-func (d LocalDate) In(loc *time.Location) time.Time {
-	return time.Date(d.Year, d.Month, d.Day, 0, 0, 0, 0, loc)
-}
-
-// AddDays returns the date that is n days in the future.
-// n can also be negative to go into the past.
-func (d LocalDate) AddDays(n int) LocalDate {
-	return LocalDateOf(d.In(time.UTC).AddDate(0, 0, n))
-}
-
-// DaysSince returns the signed number of days between the date and s, not including the end day.
-// This is the inverse operation to AddDays.
-func (d LocalDate) DaysSince(s LocalDate) (days int) {
-	// We convert to Unix time so we do not have to worry about leap seconds:
-	// Unix time increases by exactly 86400 seconds per day.
-	deltaUnix := d.In(time.UTC).Unix() - s.In(time.UTC).Unix()
-
-	const secondsInADay = 86400
-
-	return int(deltaUnix / secondsInADay)
-}
-
-// Before reports whether d1 occurs before future date.
-func (d LocalDate) Before(future LocalDate) bool {
-	if d.Year != future.Year {
-		return d.Year < future.Year
-	}
-
-	if d.Month != future.Month {
-		return d.Month < future.Month
-	}
-
-	return d.Day < future.Day
-}
-
-// After reports whether d1 occurs after past date.
-func (d LocalDate) After(past LocalDate) bool {
-	return past.Before(d)
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-// The output is the result of d.String().
+// MarshalText returns RFC 3339 representation of d.
 func (d LocalDate) MarshalText() ([]byte, error) {
 	return []byte(d.String()), nil
 }
 
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-// The date is expected to be a string in a format accepted by ParseLocalDate.
-func (d *LocalDate) UnmarshalText(data []byte) error {
-	var err error
-	*d, err = ParseLocalDate(string(data))
-
-	return err
-}
-
-// A LocalTime represents a time with nanosecond precision.
-//
-// This type does not include location information, and therefore does not
-// describe a unique moment in time.
-//
-// This type exists to represent the TIME type in storage-based APIs like BigQuery.
-// Most operations on Times are unlikely to be meaningful. Prefer the LocalDateTime type.
-type LocalTime struct {
-	Hour       int // The hour of the day in 24-hour format; range [0-23]
-	Minute     int // The minute of the hour; range [0-59]
-	Second     int // The second of the minute; range [0-59]
-	Nanosecond int // The nanosecond of the second; range [0-999999999]
-}
-
-// LocalTimeOf returns the LocalTime representing the time of day in which a time occurs
-// in that time's location. It ignores the date.
-func LocalTimeOf(t time.Time) LocalTime {
-	var tm LocalTime
-	tm.Hour, tm.Minute, tm.Second = t.Clock()
-	tm.Nanosecond = t.Nanosecond()
-
-	return tm
-}
-
-// ParseLocalTime parses a string and returns the time value it represents.
-// ParseLocalTime accepts an extended form of the RFC3339 partial-time format. After
-// the HH:MM:SS part of the string, an optional fractional part may appear,
-// consisting of a decimal point followed by one to nine decimal digits.
-// (RFC3339 admits only one digit after the decimal point).
-func ParseLocalTime(s string) (LocalTime, error) {
-	t, err := time.Parse("15:04:05.999999999", s)
+// UnmarshalText parses b using RFC 3339 to fill d.
+func (d *LocalDate) UnmarshalText(b []byte) error {
+	res, err := parseLocalDate(b)
 	if err != nil {
-		return LocalTime{}, err
+		return err
 	}
-
-	return LocalTimeOf(t), nil
+	*d = res
+	return nil
 }
 
-// String returns the date in the format described in ParseLocalTime. If Nanoseconds
-// is zero, no fractional part will be generated. Otherwise, the result will
-// end with a fractional part consisting of a decimal point and nine digits.
-func (t LocalTime) String() string {
-	s := fmt.Sprintf("%02d:%02d:%02d", t.Hour, t.Minute, t.Second)
-	if t.Nanosecond == 0 {
-		return s
+// LocalTime represents a time of day of no specific day in no specific
+// timezone.
+type LocalTime struct {
+	Hour       int // Hour of the day: [0; 24[
+	Minute     int // Minute of the hour: [0; 60[
+	Second     int // Second of the minute: [0; 60[
+	Nanosecond int // Nanoseconds within the second:  [0, 1000000000[
+	Precision  int // Number of digits to display for Nanosecond.
+}
+
+// String returns RFC 3339 representation of d.
+// If d.Nanosecond and d.Precision are zero, the time won't have a nanosecond
+// component. If d.Nanosecond > 0 but d.Precision = 0, then the minimum number
+// of digits for nanoseconds is provided.
+func (d LocalTime) String() string {
+	s := fmt.Sprintf("%02d:%02d:%02d", d.Hour, d.Minute, d.Second)
+
+	if d.Precision > 0 {
+		s += fmt.Sprintf(".%09d", d.Nanosecond)[:d.Precision+1]
+	} else if d.Nanosecond > 0 {
+		// Nanoseconds are specified, but precision is not provided. Use the
+		// minimum.
+		s += strings.Trim(fmt.Sprintf(".%09d", d.Nanosecond), "0")
 	}
 
-	return s + fmt.Sprintf(".%09d", t.Nanosecond)
-}
-
-// IsValid reports whether the time is valid.
-func (t LocalTime) IsValid() bool {
-	// Construct a non-zero time.
-	tm := time.Date(2, 2, 2, t.Hour, t.Minute, t.Second, t.Nanosecond, time.UTC)
-
-	return LocalTimeOf(tm) == t
-}
-
-// MarshalText implements the encoding.TextMarshaler interface.
-// The output is the result of t.String().
-func (t LocalTime) MarshalText() ([]byte, error) {
-	return []byte(t.String()), nil
-}
-
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-// The time is expected to be a string in a format accepted by ParseLocalTime.
-func (t *LocalTime) UnmarshalText(data []byte) error {
-	var err error
-	*t, err = ParseLocalTime(string(data))
-
-	return err
+	return s
 }
 
-// A LocalDateTime represents a date and time.
-//
-// This type does not include location information, and therefore does not
-// describe a unique moment in time.
-type LocalDateTime struct {
-	Date LocalDate
-	Time LocalTime
+// MarshalText returns RFC 3339 representation of d.
+func (d LocalTime) MarshalText() ([]byte, error) {
+	return []byte(d.String()), nil
 }
 
-// Note: We deliberately do not embed LocalDate into LocalDateTime, to avoid promoting AddDays and Sub.
-
-// LocalDateTimeOf returns the LocalDateTime in which a time occurs in that time's location.
-func LocalDateTimeOf(t time.Time) LocalDateTime {
-	return LocalDateTime{
-		Date: LocalDateOf(t),
-		Time: LocalTimeOf(t),
+// UnmarshalText parses b using RFC 3339 to fill d.
+func (d *LocalTime) UnmarshalText(b []byte) error {
+	res, left, err := parseLocalTime(b)
+	if err == nil && len(left) != 0 {
+		err = newDecodeError(left, "extra characters")
 	}
-}
-
-// ParseLocalDateTime parses a string and returns the LocalDateTime it represents.
-// ParseLocalDateTime accepts a variant of the RFC3339 date-time format that omits
-// the time offset but includes an optional fractional time, as described in
-// ParseLocalTime. Informally, the accepted format is
-//     YYYY-MM-DDTHH:MM:SS[.FFFFFFFFF]
-// where the 'T' may be a lower-case 't'.
-func ParseLocalDateTime(s string) (LocalDateTime, error) {
-	t, err := time.Parse("2006-01-02T15:04:05.999999999", s)
 	if err != nil {
-		t, err = time.Parse("2006-01-02t15:04:05.999999999", s)
-		if err != nil {
-			return LocalDateTime{}, err
-		}
+		return err
 	}
-
-	return LocalDateTimeOf(t), nil
-}
-
-// String returns the date in the format described in ParseLocalDate.
-func (dt LocalDateTime) String() string {
-	return dt.Date.String() + "T" + dt.Time.String()
+	*d = res
+	return nil
 }
 
-// IsValid reports whether the datetime is valid.
-func (dt LocalDateTime) IsValid() bool {
-	return dt.Date.IsValid() && dt.Time.IsValid()
-}
-
-// In returns the time corresponding to the LocalDateTime in the given location.
-//
-// If the time is missing or ambigous at the location, In returns the same
-// result as time.LocalDate. For example, if loc is America/Indiana/Vincennes, then
-// both
-//     time.LocalDate(1955, time.May, 1, 0, 30, 0, 0, loc)
-// and
-//     civil.LocalDateTime{
-//         civil.LocalDate{Year: 1955, Month: time.May, Day: 1}},
-//         civil.LocalTime{Minute: 30}}.In(loc)
-// return 23:30:00 on April 30, 1955.
-//
-// In panics if loc is nil.
-func (dt LocalDateTime) In(loc *time.Location) time.Time {
-	return time.Date(
-		dt.Date.Year, dt.Date.Month, dt.Date.Day,
-		dt.Time.Hour, dt.Time.Minute, dt.Time.Second, dt.Time.Nanosecond, loc,
-	)
+// LocalDateTime represents a time of a specific day in no specific timezone.
+type LocalDateTime struct {
+	LocalDate
+	LocalTime
 }
 
-// Before reports whether dt occurs before future.
-func (dt LocalDateTime) Before(future LocalDateTime) bool {
-	return dt.In(time.UTC).Before(future.In(time.UTC))
+// AsTime converts d into a specific time instance in zone.
+func (d LocalDateTime) AsTime(zone *time.Location) time.Time {
+	return time.Date(d.Year, time.Month(d.Month), d.Day, d.Hour, d.Minute, d.Second, d.Nanosecond, zone)
 }
 
-// After reports whether dt occurs after past.
-func (dt LocalDateTime) After(past LocalDateTime) bool {
-	return past.Before(dt)
+// String returns RFC 3339 representation of d.
+func (d LocalDateTime) String() string {
+	return d.LocalDate.String() + "T" + d.LocalTime.String()
 }
 
-// MarshalText implements the encoding.TextMarshaler interface.
-// The output is the result of dt.String().
-func (dt LocalDateTime) MarshalText() ([]byte, error) {
-	return []byte(dt.String()), nil
+// MarshalText returns RFC 3339 representation of d.
+func (d LocalDateTime) MarshalText() ([]byte, error) {
+	return []byte(d.String()), nil
 }
 
-// UnmarshalText implements the encoding.TextUnmarshaler interface.
-// The datetime is expected to be a string in a format accepted by ParseLocalDateTime.
-func (dt *LocalDateTime) UnmarshalText(data []byte) error {
-	var err error
-	*dt, err = ParseLocalDateTime(string(data))
+// UnmarshalText parses b using RFC 3339 to fill d.
+func (d *LocalDateTime) UnmarshalText(data []byte) error {
+	res, left, err := parseLocalDateTime(data)
+	if err == nil && len(left) != 0 {
+		err = newDecodeError(left, "extra characters")
+	}
+	if err != nil {
+		return err
+	}
 
-	return err
+	*d = res
+	return nil
 }
diff --git a/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/marshaler.go
index ce9972aae..acb288315 100644
--- a/vendor/github.com/pelletier/go-toml/v2/marshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/marshaler.go
@@ -5,11 +5,13 @@ import (
 	"encoding"
 	"fmt"
 	"io"
+	"math"
 	"reflect"
 	"sort"
 	"strconv"
 	"strings"
 	"time"
+	"unicode"
 )
 
 // Marshal serializes a Go value as a TOML document.
@@ -52,9 +54,10 @@ func NewEncoder(w io.Writer) *Encoder {
 // This behavior can be controlled on an individual struct field basis with the
 // inline tag:
 //
-//   MyField `inline:"true"`
-func (enc *Encoder) SetTablesInline(inline bool) {
+//	MyField `toml:",inline"`
+func (enc *Encoder) SetTablesInline(inline bool) *Encoder {
 	enc.tablesInline = inline
+	return enc
 }
 
 // SetArraysMultiline forces the encoder to emit all arrays with one element per
@@ -62,28 +65,31 @@ func (enc *Encoder) SetTablesInline(inline bool) {
 //
 // This behavior can be controlled on an individual struct field basis with the multiline tag:
 //
-//   MyField `multiline:"true"`
-func (enc *Encoder) SetArraysMultiline(multiline bool) {
+//	MyField `multiline:"true"`
+func (enc *Encoder) SetArraysMultiline(multiline bool) *Encoder {
 	enc.arraysMultiline = multiline
+	return enc
 }
 
 // SetIndentSymbol defines the string that should be used for indentation. The
 // provided string is repeated for each indentation level. Defaults to two
 // spaces.
-func (enc *Encoder) SetIndentSymbol(s string) {
+func (enc *Encoder) SetIndentSymbol(s string) *Encoder {
 	enc.indentSymbol = s
+	return enc
 }
 
 // SetIndentTables forces the encoder to intent tables and array tables.
-func (enc *Encoder) SetIndentTables(indent bool) {
+func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
 	enc.indentTables = indent
+	return enc
 }
 
 // Encode writes a TOML representation of v to the stream.
 //
 // If v cannot be represented to TOML it returns an error.
 //
-// Encoding rules
+// # Encoding rules
 //
 // A top level slice containing only maps or structs is encoded as [[table
 // array]].
@@ -98,27 +104,52 @@ func (enc *Encoder) SetIndentTables(indent bool) {
 // Intermediate tables are always printed.
 //
 // By default, strings are encoded as literal string, unless they contain either
-// a newline character or a single quote. In that case they are emitted as quoted
-// strings.
+// a newline character or a single quote. In that case they are emitted as
+// quoted strings.
+//
+// Unsigned integers larger than math.MaxInt64 cannot be encoded. Doing so
+// results in an error. This rule exists because the TOML specification only
+// requires parsers to support at least the 64 bits integer range. Allowing
+// larger numbers would create non-standard TOML documents, which may not be
+// readable (at best) by other implementations. To encode such numbers, a
+// solution is a custom type that implements encoding.TextMarshaler.
 //
 // When encoding structs, fields are encoded in order of definition, with their
 // exact name.
 //
-// Struct tags
+// Tables and array tables are separated by empty lines. However, consecutive
+// subtables definitions are not. For example:
+//
+//	[top1]
+//
+//	[top2]
+//	[top2.child1]
+//
+//	[[array]]
+//
+//	[[array]]
+//	[array.child2]
 //
-// The following struct tags are available to tweak encoding on a per-field
-// basis:
+// # Struct tags
 //
-//   toml:"foo"
-//     Changes the name of the key to use for the field to foo.
+// The encoding of each public struct field can be customized by the format
+// string in the "toml" key of the struct field's tag. This follows
+// encoding/json's convention. The format string starts with the name of the
+// field, optionally followed by a comma-separated list of options. The name may
+// be empty in order to provide options without overriding the default name.
 //
-//   multiline:"true"
-//     When the field contains a string, it will be emitted as a quoted
-//     multi-line TOML string.
+// The "multiline" option emits strings as quoted multi-line TOML strings. It
+// has no effect on fields that would not be encoded as strings.
 //
-//   inline:"true"
-//     When the field would normally be encoded as a table, it is instead
-//     encoded as an inline table.
+// The "inline" option turns fields that would be emitted as tables into inline
+// tables instead. It has no effect on other fields.
+//
+// The "omitempty" option prevents empty values or groups from being emitted.
+//
+// In addition to the "toml" tag struct tag, a "comment" tag can be used to emit
+// a TOML comment before the value being annotated. Comments are ignored inside
+// inline tables. For array tables, the comment is only present before the first
+// element of the array.
 func (enc *Encoder) Encode(v interface{}) error {
 	var (
 		b   []byte
@@ -146,6 +177,8 @@ func (enc *Encoder) Encode(v interface{}) error {
 
 type valueOptions struct {
 	multiline bool
+	omitempty bool
+	comment   string
 }
 
 type encoderCtx struct {
@@ -195,16 +228,29 @@ func (ctx *encoderCtx) isRoot() bool {
 	return len(ctx.parentKey) == 0 && !ctx.hasKey
 }
 
-//nolint:cyclop,funlen
 func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
-	if !v.IsZero() {
-		i, ok := v.Interface().(time.Time)
-		if ok {
-			return i.AppendFormat(b, time.RFC3339), nil
+	i := v.Interface()
+
+	switch x := i.(type) {
+	case time.Time:
+		if x.Nanosecond() > 0 {
+			return x.AppendFormat(b, time.RFC3339Nano), nil
 		}
+		return x.AppendFormat(b, time.RFC3339), nil
+	case LocalTime:
+		return append(b, x.String()...), nil
+	case LocalDate:
+		return append(b, x.String()...), nil
+	case LocalDateTime:
+		return append(b, x.String()...), nil
 	}
 
-	if v.Type().Implements(textMarshalerType) {
+	hasTextMarshaler := v.Type().Implements(textMarshalerType)
+	if hasTextMarshaler || (v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) {
+		if !hasTextMarshaler {
+			v = v.Addr()
+		}
+
 		if ctx.isRoot() {
 			return nil, fmt.Errorf("toml: type %s implementing the TextMarshaler interface cannot be a root element", v.Type())
 		}
@@ -244,9 +290,32 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
 	case reflect.String:
 		b = enc.encodeString(b, v.String(), ctx.options)
 	case reflect.Float32:
-		b = strconv.AppendFloat(b, v.Float(), 'f', -1, 32)
+		f := v.Float()
+
+		if math.IsNaN(f) {
+			b = append(b, "nan"...)
+		} else if f > math.MaxFloat32 {
+			b = append(b, "inf"...)
+		} else if f < -math.MaxFloat32 {
+			b = append(b, "-inf"...)
+		} else if math.Trunc(f) == f {
+			b = strconv.AppendFloat(b, f, 'f', 1, 32)
+		} else {
+			b = strconv.AppendFloat(b, f, 'f', -1, 32)
+		}
 	case reflect.Float64:
-		b = strconv.AppendFloat(b, v.Float(), 'f', -1, 64)
+		f := v.Float()
+		if math.IsNaN(f) {
+			b = append(b, "nan"...)
+		} else if f > math.MaxFloat64 {
+			b = append(b, "inf"...)
+		} else if f < -math.MaxFloat64 {
+			b = append(b, "-inf"...)
+		} else if math.Trunc(f) == f {
+			b = strconv.AppendFloat(b, f, 'f', 1, 64)
+		} else {
+			b = strconv.AppendFloat(b, f, 'f', -1, 64)
+		}
 	case reflect.Bool:
 		if v.Bool() {
 			b = append(b, "true"...)
@@ -254,7 +323,11 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
 			b = append(b, "false"...)
 		}
 	case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
-		b = strconv.AppendUint(b, v.Uint(), 10)
+		x := v.Uint()
+		if x > uint64(math.MaxInt64) {
+			return nil, fmt.Errorf("toml: not encoding uint (%d) greater than max int64 (%d)", x, int64(math.MaxInt64))
+		}
+		b = strconv.AppendUint(b, x, 10)
 	case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
 		b = strconv.AppendInt(b, v.Int(), 10)
 	default:
@@ -273,19 +346,19 @@ func isNil(v reflect.Value) bool {
 	}
 }
 
+func shouldOmitEmpty(options valueOptions, v reflect.Value) bool {
+	return options.omitempty && isEmptyValue(v)
+}
+
 func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) {
 	var err error
 
-	if !ctx.hasKey {
-		panic("caller of encodeKv should have set the key in the context")
-	}
-	b = enc.indent(ctx.indent, b)
-
-	b, err = enc.encodeKey(b, ctx.key)
-	if err != nil {
-		return nil, err
+	if !ctx.inline {
+		b = enc.encodeComment(ctx.indent, options.comment, b)
 	}
 
+	b = enc.indent(ctx.indent, b)
+	b = enc.encodeKey(b, ctx.key)
 	b = append(b, " = "...)
 
 	// create a copy of the context because the value of a KV shouldn't
@@ -303,6 +376,54 @@ func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v r
 	return b, nil
 }
 
+func isEmptyValue(v reflect.Value) bool {
+	switch v.Kind() {
+	case reflect.Struct:
+		return isEmptyStruct(v)
+	case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
+		return v.Len() == 0
+	case reflect.Bool:
+		return !v.Bool()
+	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+		return v.Int() == 0
+	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+		return v.Uint() == 0
+	case reflect.Float32, reflect.Float64:
+		return v.Float() == 0
+	case reflect.Interface, reflect.Ptr:
+		return v.IsNil()
+	}
+	return false
+}
+
+func isEmptyStruct(v reflect.Value) bool {
+	// TODO: merge with walkStruct and cache.
+	typ := v.Type()
+	for i := 0; i < typ.NumField(); i++ {
+		fieldType := typ.Field(i)
+
+		// only consider exported fields
+		if fieldType.PkgPath != "" {
+			continue
+		}
+
+		tag := fieldType.Tag.Get("toml")
+
+		// special field name to skip field
+		if tag == "-" {
+			continue
+		}
+
+		f := v.Field(i)
+
+		if !isEmptyValue(f) {
+			return false
+		}
+	}
+
+	return true
+}
+
 const literalQuote = '\''
 
 func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byte {
@@ -314,7 +435,13 @@ func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byt
 }
 
 func needsQuoting(v string) bool {
-	return strings.ContainsAny(v, "'\b\f\n\r\t")
+	// TODO: vectorize
+	for _, b := range []byte(v) {
+		if b == '\'' || b == '\r' || b == '\n' || invalidAscii(b) {
+			return true
+		}
+	}
+	return false
 }
 
 // caller should have checked that the string does not contain new lines or ' .
@@ -326,7 +453,6 @@ func (enc *Encoder) encodeLiteralString(b []byte, v string) []byte {
 	return b
 }
 
-//nolint:cyclop
 func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byte {
 	stringQuote := `"`
 
@@ -386,7 +512,7 @@ func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byt
 	return b
 }
 
-// called should have checked that the string is in A-Z / a-z / 0-9 / - / _ .
+// caller should have checked that the string is in A-Z / a-z / 0-9 / - / _ .
 func (enc *Encoder) encodeUnquotedKey(b []byte, v string) []byte {
 	return append(b, v...)
 }
@@ -396,24 +522,17 @@ func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error)
 		return b, nil
 	}
 
+	b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
+
 	b = enc.indent(ctx.indent, b)
 
 	b = append(b, '[')
 
-	var err error
-
-	b, err = enc.encodeKey(b, ctx.parentKey[0])
-	if err != nil {
-		return nil, err
-	}
+	b = enc.encodeKey(b, ctx.parentKey[0])
 
 	for _, k := range ctx.parentKey[1:] {
 		b = append(b, '.')
-
-		b, err = enc.encodeKey(b, k)
-		if err != nil {
-			return nil, err
-		}
+		b = enc.encodeKey(b, k)
 	}
 
 	b = append(b, "]\n"...)
@@ -422,19 +541,19 @@ func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error)
 }
 
 //nolint:cyclop
-func (enc *Encoder) encodeKey(b []byte, k string) ([]byte, error) {
+func (enc *Encoder) encodeKey(b []byte, k string) []byte {
 	needsQuotation := false
 	cannotUseLiteral := false
 
+	if len(k) == 0 {
+		return append(b, "''"...)
+	}
+
 	for _, c := range k {
 		if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' {
 			continue
 		}
 
-		if c == '\n' {
-			return nil, fmt.Errorf("toml: new line characters in keys are not supported")
-		}
-
 		if c == literalQuote {
 			cannotUseLiteral = true
 		}
@@ -442,13 +561,17 @@ func (enc *Encoder) encodeKey(b []byte, k string) ([]byte, error) {
 		needsQuotation = true
 	}
 
+	if needsQuotation && needsQuoting(k) {
+		cannotUseLiteral = true
+	}
+
 	switch {
 	case cannotUseLiteral:
-		return enc.encodeQuotedString(false, b, k), nil
+		return enc.encodeQuotedString(false, b, k)
 	case needsQuotation:
-		return enc.encodeLiteralString(b, k), nil
+		return enc.encodeLiteralString(b, k)
 	default:
-		return enc.encodeUnquotedKey(b, k), nil
+		return enc.encodeUnquotedKey(b, k)
 	}
 }
 
@@ -502,18 +625,26 @@ type table struct {
 }
 
 func (t *table) pushKV(k string, v reflect.Value, options valueOptions) {
+	for _, e := range t.kvs {
+		if e.Key == k {
+			return
+		}
+	}
+
 	t.kvs = append(t.kvs, entry{Key: k, Value: v, Options: options})
 }
 
 func (t *table) pushTable(k string, v reflect.Value, options valueOptions) {
+	for _, e := range t.tables {
+		if e.Key == k {
+			return
+		}
+	}
 	t.tables = append(t.tables, entry{Key: k, Value: v, Options: options})
 }
 
-func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
-	var t table
-
-	//nolint:godox
-	// TODO: cache this?
+func walkStruct(ctx encoderCtx, t *table, v reflect.Value) {
+	// TODO: cache this
 	typ := v.Type()
 	for i := 0; i < typ.NumField(); i++ {
 		fieldType := typ.Field(i)
@@ -523,45 +654,130 @@ func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]b
 			continue
 		}
 
-		k, ok := fieldType.Tag.Lookup("toml")
-		if !ok {
-			k = fieldType.Name
-		}
+		tag := fieldType.Tag.Get("toml")
 
 		// special field name to skip field
-		if k == "-" {
+		if tag == "-" {
 			continue
 		}
 
+		k, opts := parseTag(tag)
+		if !isValidName(k) {
+			k = ""
+		}
+
 		f := v.Field(i)
 
+		if k == "" {
+			if fieldType.Anonymous {
+				if fieldType.Type.Kind() == reflect.Struct {
+					walkStruct(ctx, t, f)
+				}
+				continue
+			} else {
+				k = fieldType.Name
+			}
+		}
+
 		if isNil(f) {
 			continue
 		}
 
 		options := valueOptions{
-			multiline: fieldBoolTag(fieldType, "multiline"),
+			multiline: opts.multiline,
+			omitempty: opts.omitempty,
+			comment:   fieldType.Tag.Get("comment"),
 		}
 
-		inline := fieldBoolTag(fieldType, "inline")
-
-		if inline || !willConvertToTableOrArrayTable(ctx, f) {
+		if opts.inline || !willConvertToTableOrArrayTable(ctx, f) {
 			t.pushKV(k, f, options)
 		} else {
 			t.pushTable(k, f, options)
 		}
 	}
+}
+
+func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
+	var t table
+
+	walkStruct(ctx, &t, v)
 
 	return enc.encodeTable(b, ctx, t)
 }
 
-func fieldBoolTag(field reflect.StructField, tag string) bool {
-	x, ok := field.Tag.Lookup(tag)
+func (enc *Encoder) encodeComment(indent int, comment string, b []byte) []byte {
+	for len(comment) > 0 {
+		var line string
+		idx := strings.IndexByte(comment, '\n')
+		if idx >= 0 {
+			line = comment[:idx]
+			comment = comment[idx+1:]
+		} else {
+			line = comment
+			comment = ""
+		}
+		b = enc.indent(indent, b)
+		b = append(b, "# "...)
+		b = append(b, line...)
+		b = append(b, '\n')
+	}
+	return b
+}
+
+func isValidName(s string) bool {
+	if s == "" {
+		return false
+	}
+	for _, c := range s {
+		switch {
+		case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
+			// Backslash and quote chars are reserved, but
+			// otherwise any punctuation chars are allowed
+			// in a tag name.
+		case !unicode.IsLetter(c) && !unicode.IsDigit(c):
+			return false
+		}
+	}
+	return true
+}
 
-	return ok && x == "true"
+type tagOptions struct {
+	multiline bool
+	inline    bool
+	omitempty bool
+}
+
+func parseTag(tag string) (string, tagOptions) {
+	opts := tagOptions{}
+
+	idx := strings.Index(tag, ",")
+	if idx == -1 {
+		return tag, opts
+	}
+
+	raw := tag[idx+1:]
+	tag = string(tag[:idx])
+	for raw != "" {
+		var o string
+		i := strings.Index(raw, ",")
+		if i >= 0 {
+			o, raw = raw[:i], raw[i+1:]
+		} else {
+			o, raw = raw, ""
+		}
+		switch o {
+		case "multiline":
+			opts.multiline = true
+		case "inline":
+			opts.inline = true
+		case "omitempty":
+			opts.omitempty = true
+		}
+	}
+
+	return tag, opts
 }
 
-//nolint:cyclop
 func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, error) {
 	var err error
 
@@ -583,7 +799,13 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
 	}
 	ctx.skipTableHeader = false
 
+	hasNonEmptyKV := false
 	for _, kv := range t.kvs {
+		if shouldOmitEmpty(kv.Options, kv.Value) {
+			continue
+		}
+		hasNonEmptyKV = true
+
 		ctx.setKey(kv.Key)
 
 		b, err = enc.encodeKv(b, ctx, kv.Options, kv.Value)
@@ -594,7 +816,20 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
 		b = append(b, '\n')
 	}
 
+	first := true
 	for _, table := range t.tables {
+		if shouldOmitEmpty(table.Options, table.Value) {
+			continue
+		}
+		if first {
+			first = false
+			if hasNonEmptyKV {
+				b = append(b, '\n')
+			}
+		} else {
+			b = append(b, "\n"...)
+		}
+
 		ctx.setKey(table.Key)
 
 		ctx.options = table.Options
@@ -603,8 +838,6 @@ func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, erro
 		if err != nil {
 			return nil, err
 		}
-
-		b = append(b, '\n')
 	}
 
 	return b, nil
@@ -617,6 +850,10 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
 
 	first := true
 	for _, kv := range t.kvs {
+		if shouldOmitEmpty(kv.Options, kv.Value) {
+			continue
+		}
+
 		if first {
 			first = false
 		} else {
@@ -632,7 +869,7 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
 	}
 
 	if len(t.tables) > 0 {
-		panic("inline table cannot contain nested tables, online key-values")
+		panic("inline table cannot contain nested tables, only key-values")
 	}
 
 	b = append(b, "}"...)
@@ -640,10 +877,11 @@ func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte
 	return b, nil
 }
 
-var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
-
 func willConvertToTable(ctx encoderCtx, v reflect.Value) bool {
-	if v.Type() == timeType || v.Type().Implements(textMarshalerType) {
+	if !v.IsValid() {
+		return false
+	}
+	if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PtrTo(v.Type()).Implements(textMarshalerType)) {
 		return false
 	}
 
@@ -665,6 +903,9 @@ func willConvertToTable(ctx encoderCtx, v reflect.Value) bool {
 }
 
 func willConvertToTableOrArrayTable(ctx encoderCtx, v reflect.Value) bool {
+	if ctx.insideKv {
+		return false
+	}
 	t := v.Type()
 
 	if t.Kind() == reflect.Interface {
@@ -710,7 +951,6 @@ func (enc *Encoder) encodeSlice(b []byte, ctx encoderCtx, v reflect.Value) ([]by
 func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) {
 	ctx.shiftKey()
 
-	var err error
 	scratch := make([]byte, 0, 64)
 	scratch = append(scratch, "[["...)
 
@@ -719,18 +959,22 @@ func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.
 			scratch = append(scratch, '.')
 		}
 
-		scratch, err = enc.encodeKey(scratch, k)
-		if err != nil {
-			return nil, err
-		}
+		scratch = enc.encodeKey(scratch, k)
 	}
 
 	scratch = append(scratch, "]]\n"...)
 	ctx.skipTableHeader = true
 
+	b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
+
 	for i := 0; i < v.Len(); i++ {
+		if i != 0 {
+			b = append(b, "\n"...)
+		}
+
 		b = append(b, scratch...)
 
+		var err error
 		b, err = enc.encode(b, ctx, v.Index(i))
 		if err != nil {
 			return nil, err
diff --git a/vendor/github.com/pelletier/go-toml/v2/parser.go b/vendor/github.com/pelletier/go-toml/v2/parser.go
index eefbf032a..9859a795b 100644
--- a/vendor/github.com/pelletier/go-toml/v2/parser.go
+++ b/vendor/github.com/pelletier/go-toml/v2/parser.go
@@ -2,9 +2,10 @@ package toml
 
 import (
 	"bytes"
-	"strconv"
+	"unicode"
 
 	"github.com/pelletier/go-toml/v2/internal/ast"
+	"github.com/pelletier/go-toml/v2/internal/danger"
 )
 
 type parser struct {
@@ -16,9 +17,20 @@ type parser struct {
 	first   bool
 }
 
+func (p *parser) Range(b []byte) ast.Range {
+	return ast.Range{
+		Offset: uint32(danger.SubsliceOffset(p.data, b)),
+		Length: uint32(len(b)),
+	}
+}
+
+func (p *parser) Raw(raw ast.Range) []byte {
+	return p.data[raw.Offset : raw.Offset+raw.Length]
+}
+
 func (p *parser) Reset(b []byte) {
 	p.builder.Reset()
-	p.ref = ast.Reference{}
+	p.ref = ast.InvalidReference
 	p.data = b
 	p.left = b
 	p.err = nil
@@ -32,7 +44,7 @@ func (p *parser) NextExpression() bool {
 	}
 
 	p.builder.Reset()
-	p.ref = ast.Reference{}
+	p.ref = ast.InvalidReference
 
 	for {
 		if len(p.left) == 0 || p.err != nil {
@@ -61,7 +73,7 @@ func (p *parser) NextExpression() bool {
 	}
 }
 
-func (p *parser) Expression() ast.Node {
+func (p *parser) Expression() *ast.Node {
 	return p.builder.NodeAt(p.ref)
 }
 
@@ -86,7 +98,7 @@ func (p *parser) parseExpression(b []byte) (ast.Reference, []byte, error) {
 	// expression =  ws [ comment ]
 	// expression =/ ws keyval ws [ comment ]
 	// expression =/ ws table ws [ comment ]
-	var ref ast.Reference
+	ref := ast.InvalidReference
 
 	b = p.parseWhitespace(b)
 
@@ -95,9 +107,8 @@ func (p *parser) parseExpression(b []byte) (ast.Reference, []byte, error) {
 	}
 
 	if b[0] == '#' {
-		_, rest := scanComment(b)
-
-		return ref, rest, nil
+		_, rest, err := scanComment(b)
+		return ref, rest, err
 	}
 
 	if b[0] == '\n' || b[0] == '\r' {
@@ -118,9 +129,8 @@ func (p *parser) parseExpression(b []byte) (ast.Reference, []byte, error) {
 	b = p.parseWhitespace(b)
 
 	if len(b) > 0 && b[0] == '#' {
-		_, rest := scanComment(b)
-
-		return ref, rest, nil
+		_, rest, err := scanComment(b)
+		return ref, rest, err
 	}
 
 	return ref, b, nil
@@ -197,7 +207,7 @@ func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
 
 	key, b, err := p.parseKey(b)
 	if err != nil {
-		return ast.Reference{}, nil, err
+		return ast.InvalidReference, nil, err
 	}
 
 	// keyval-sep = ws %x3D ws ; =
@@ -205,12 +215,12 @@ func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
 	b = p.parseWhitespace(b)
 
 	if len(b) == 0 {
-		return ast.Reference{}, nil, newDecodeError(b, "expected = after a key, but the document ends there")
+		return ast.InvalidReference, nil, newDecodeError(b, "expected = after a key, but the document ends there")
 	}
 
 	b, err = expect('=', b)
 	if err != nil {
-		return ast.Reference{}, nil, err
+		return ast.InvalidReference, nil, err
 	}
 
 	b = p.parseWhitespace(b)
@@ -229,7 +239,7 @@ func (p *parser) parseKeyval(b []byte) (ast.Reference, []byte, error) {
 //nolint:cyclop,funlen
 func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
 	// val = string / boolean / array / inline-table / date-time / float / integer
-	var ref ast.Reference
+	ref := ast.InvalidReference
 
 	if len(b) == 0 {
 		return ref, nil, newDecodeError(b, "expected value, not eof")
@@ -240,32 +250,36 @@ func (p *parser) parseVal(b []byte) (ast.Reference, []byte, error) {
 
 	switch c {
 	case '"':
+		var raw []byte
 		var v []byte
 		if scanFollowsMultilineBasicStringDelimiter(b) {
-			v, b, err = p.parseMultilineBasicString(b)
+			raw, v, b, err = p.parseMultilineBasicString(b)
 		} else {
-			v, b, err = p.parseBasicString(b)
+			raw, v, b, err = p.parseBasicString(b)
 		}
 
 		if err == nil {
 			ref = p.builder.Push(ast.Node{
 				Kind: ast.String,
+				Raw:  p.Range(raw),
 				Data: v,
 			})
 		}
 
 		return ref, b, err
 	case '\'':
+		var raw []byte
 		var v []byte
 		if scanFollowsMultilineLiteralStringDelimiter(b) {
-			v, b, err = p.parseMultilineLiteralString(b)
+			raw, v, b, err = p.parseMultilineLiteralString(b)
 		} else {
-			v, b, err = p.parseLiteralString(b)
+			raw, v, b, err = p.parseLiteralString(b)
 		}
 
 		if err == nil {
 			ref = p.builder.Push(ast.Node{
 				Kind: ast.String,
+				Raw:  p.Range(raw),
 				Data: v,
 			})
 		}
@@ -310,13 +324,13 @@ func atmost(b []byte, n int) []byte {
 	return b[:n]
 }
 
-func (p *parser) parseLiteralString(b []byte) ([]byte, []byte, error) {
+func (p *parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) {
 	v, rest, err := scanLiteralString(b)
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
-	return v[1 : len(v)-1], rest, nil
+	return v, v[1 : len(v)-1], rest, nil
 }
 
 func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
@@ -338,7 +352,13 @@ func (p *parser) parseInlineTable(b []byte) (ast.Reference, []byte, error) {
 	var err error
 
 	for len(b) > 0 {
+		previousB := b
 		b = p.parseWhitespace(b)
+
+		if len(b) == 0 {
+			return parent, nil, newDecodeError(previousB[:1], "inline table is incomplete")
+		}
+
 		if b[0] == '}' {
 			break
 		}
@@ -382,6 +402,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
 	// array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ]
 	// array-sep = %x2C  ; , Comma
 	// ws-comment-newline = *( wschar / [ comment ] newline )
+	arrayStart := b
 	b = b[1:]
 
 	parent := p.builder.Push(ast.Node{
@@ -400,7 +421,7 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
 		}
 
 		if len(b) == 0 {
-			return parent, nil, newDecodeError(b, "array is incomplete")
+			return parent, nil, newDecodeError(arrayStart[:1], "array is incomplete")
 		}
 
 		if b[0] == ']' {
@@ -417,6 +438,8 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
 			if err != nil {
 				return parent, nil, err
 			}
+		} else if !first {
+			return parent, nil, newDecodeError(b[0:1], "array elements must be separated by commas")
 		}
 
 		// TOML allows trailing commas in arrays.
@@ -425,7 +448,6 @@ func (p *parser) parseValArray(b []byte) (ast.Reference, []byte, error) {
 		}
 
 		var valueRef ast.Reference
-
 		valueRef, b, err = p.parseVal(b)
 		if err != nil {
 			return parent, nil, err
@@ -456,7 +478,10 @@ func (p *parser) parseOptionalWhitespaceCommentNewline(b []byte) ([]byte, error)
 		b = p.parseWhitespace(b)
 
 		if len(b) > 0 && b[0] == '#' {
-			_, b = scanComment(b)
+			_, b, err = scanComment(b)
+			if err != nil {
+				return nil, err
+			}
 		}
 
 		if len(b) == 0 {
@@ -476,10 +501,10 @@ func (p *parser) parseOptionalWhitespaceCommentNewline(b []byte) ([]byte, error)
 	return b, nil
 }
 
-func (p *parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, error) {
+func (p *parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte, error) {
 	token, rest, err := scanMultilineLiteralString(b)
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
 	i := 3
@@ -491,11 +516,11 @@ func (p *parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, error) {
 		i += 2
 	}
 
-	return token[i : len(token)-3], rest, err
+	return token, token[i : len(token)-3], rest, err
 }
 
 //nolint:funlen,gocognit,cyclop
-func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
+func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, error) {
 	// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
 	// ml-basic-string-delim
 	// ml-basic-string-delim = 3quotation-mark
@@ -506,13 +531,11 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
 	// mlb-quotes = 1*2quotation-mark
 	// mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
 	// mlb-escaped-nl = escape ws newline *( wschar / newline )
-	token, rest, err := scanMultilineBasicString(b)
+	token, escaped, rest, err := scanMultilineBasicString(b)
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
 	}
 
-	var builder bytes.Buffer
-
 	i := 3
 
 	// skip the immediate new line
@@ -522,9 +545,24 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
 		i += 2
 	}
 
+	// fast path
+	startIdx := i
+	endIdx := len(token) - len(`"""`)
+
+	if !escaped {
+		str := token[startIdx:endIdx]
+		verr := utf8TomlValidAlreadyEscaped(str)
+		if verr.Zero() {
+			return token, str, rest, nil
+		}
+		return nil, nil, nil, newDecodeError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
+	}
+
+	var builder bytes.Buffer
+
 	// The scanner ensures that the token starts and ends with quotes and that
 	// escapes are balanced.
-	for ; i < len(token)-3; i++ {
+	for i < len(token)-3 {
 		c := token[i]
 
 		//nolint:nestif
@@ -532,17 +570,33 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
 			// When the last non-whitespace character on a line is an unescaped \,
 			// it will be trimmed along with all whitespace (including newlines) up
 			// to the next non-whitespace character or closing delimiter.
-			if token[i+1] == '\n' || (token[i+1] == '\r' && token[i+2] == '\n') {
-				i++ // skip the \
+
+			isLastNonWhitespaceOnLine := false
+			j := 1
+		findEOLLoop:
+			for ; j < len(token)-3-i; j++ {
+				switch token[i+j] {
+				case ' ', '\t':
+					continue
+				case '\r':
+					if token[i+j+1] == '\n' {
+						continue
+					}
+				case '\n':
+					isLastNonWhitespaceOnLine = true
+				}
+				break findEOLLoop
+			}
+			if isLastNonWhitespaceOnLine {
+				i += j
 				for ; i < len(token)-3; i++ {
 					c := token[i]
 					if !(c == '\n' || c == '\r' || c == ' ' || c == '\t') {
 						i--
-
 						break
 					}
 				}
-
+				i++
 				continue
 			}
 
@@ -563,31 +617,38 @@ func (p *parser) parseMultilineBasicString(b []byte) ([]byte, []byte, error) {
 				builder.WriteByte('\r')
 			case 't':
 				builder.WriteByte('\t')
+			case 'e':
+				builder.WriteByte(0x1B)
 			case 'u':
-				x, err := hexToString(atmost(token[i+1:], 4), 4)
+				x, err := hexToRune(atmost(token[i+1:], 4), 4)
 				if err != nil {
-					return nil, nil, err
+					return nil, nil, nil, err
 				}
-
-				builder.WriteString(x)
+				builder.WriteRune(x)
 				i += 4
 			case 'U':
-				x, err := hexToString(atmost(token[i+1:], 8), 8)
+				x, err := hexToRune(atmost(token[i+1:], 8), 8)
 				if err != nil {
-					return nil, nil, err
+					return nil, nil, nil, err
 				}
 
-				builder.WriteString(x)
+				builder.WriteRune(x)
 				i += 8
 			default:
-				return nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
+				return nil, nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
 			}
+			i++
 		} else {
-			builder.WriteByte(c)
+			size := utf8ValidNext(token[i:])
+			if size == 0 {
+				return nil, nil, nil, newDecodeError(token[i:i+1], "invalid character %#U", c)
+			}
+			builder.Write(token[i : i+size])
+			i += size
 		}
 	}
 
-	return builder.Bytes(), rest, nil
+	return token, builder.Bytes(), rest, nil
 }
 
 func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
@@ -599,13 +660,14 @@ func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
 	// dotted-key = simple-key 1*( dot-sep simple-key )
 	//
 	// dot-sep   = ws %x2E ws  ; . Period
-	key, b, err := p.parseSimpleKey(b)
+	raw, key, b, err := p.parseSimpleKey(b)
 	if err != nil {
-		return ast.Reference{}, nil, err
+		return ast.InvalidReference, nil, err
 	}
 
 	ref := p.builder.Push(ast.Node{
 		Kind: ast.Key,
+		Raw:  p.Range(raw),
 		Data: key,
 	})
 
@@ -614,13 +676,14 @@ func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
 		if len(b) > 0 && b[0] == '.' {
 			b = p.parseWhitespace(b[1:])
 
-			key, b, err = p.parseSimpleKey(b)
+			raw, key, b, err = p.parseSimpleKey(b)
 			if err != nil {
 				return ref, nil, err
 			}
 
 			p.builder.PushAndChain(ast.Node{
 				Kind: ast.Key,
+				Raw:  p.Range(raw),
 				Data: key,
 			})
 		} else {
@@ -631,14 +694,14 @@ func (p *parser) parseKey(b []byte) (ast.Reference, []byte, error) {
 	return ref, b, nil
 }
 
-func (p *parser) parseSimpleKey(b []byte) (key, rest []byte, err error) {
-	// simple-key = quoted-key / unquoted-key
-	// unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
-	// quoted-key = basic-string / literal-string
+func (p *parser) parseSimpleKey(b []byte) (raw, key, rest []byte, err error) {
 	if len(b) == 0 {
-		return nil, nil, newDecodeError(b, "key is incomplete")
+		return nil, nil, nil, newDecodeError(b, "expected key but found none")
 	}
 
+	// simple-key = quoted-key / unquoted-key
+	// unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
+	// quoted-key = basic-string / literal-string
 	switch {
 	case b[0] == '\'':
 		return p.parseLiteralString(b)
@@ -646,14 +709,14 @@ func (p *parser) parseSimpleKey(b []byte) (key, rest []byte, err error) {
 		return p.parseBasicString(b)
 	case isUnquotedKeyChar(b[0]):
 		key, rest = scanUnquotedKey(b)
-		return key, rest, nil
+		return key, key, rest, nil
 	default:
-		return nil, nil, newDecodeError(b[0:1], "invalid character at start of key: %c", b[0])
+		return nil, nil, nil, newDecodeError(b[0:1], "invalid character at start of key: %c", b[0])
 	}
 }
 
 //nolint:funlen,cyclop
-func (p *parser) parseBasicString(b []byte) ([]byte, []byte, error) {
+func (p *parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) {
 	// basic-string = quotation-mark *basic-char quotation-mark
 	// quotation-mark = %x22            ; "
 	// basic-char = basic-unescaped / escaped
@@ -668,16 +731,33 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, error) {
 	// escape-seq-char =/ %x74         ; t    tab             U+0009
 	// escape-seq-char =/ %x75 4HEXDIG ; uXXXX                U+XXXX
 	// escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX            U+XXXXXXXX
-	token, rest, err := scanBasicString(b)
+	token, escaped, rest, err := scanBasicString(b)
 	if err != nil {
-		return nil, nil, err
+		return nil, nil, nil, err
+	}
+
+	startIdx := len(`"`)
+	endIdx := len(token) - len(`"`)
+
+	// Fast path. If there is no escape sequence, the string should just be
+	// an UTF-8 encoded string, which is the same as Go. In that case,
+	// validate the string and return a direct reference to the buffer.
+	if !escaped {
+		str := token[startIdx:endIdx]
+		verr := utf8TomlValidAlreadyEscaped(str)
+		if verr.Zero() {
+			return token, str, rest, nil
+		}
+		return nil, nil, nil, newDecodeError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8")
 	}
 
+	i := startIdx
+
 	var builder bytes.Buffer
 
 	// The scanner ensures that the token starts and ends with quotes and that
 	// escapes are balanced.
-	for i := 1; i < len(token)-1; i++ {
+	for i < len(token)-1 {
 		c := token[i]
 		if c == '\\' {
 			i++
@@ -696,47 +776,68 @@ func (p *parser) parseBasicString(b []byte) ([]byte, []byte, error) {
 				builder.WriteByte('\r')
 			case 't':
 				builder.WriteByte('\t')
+			case 'e':
+				builder.WriteByte(0x1B)
 			case 'u':
-				x, err := hexToString(token[i+1:len(token)-1], 4)
+				x, err := hexToRune(token[i+1:len(token)-1], 4)
 				if err != nil {
-					return nil, nil, err
+					return nil, nil, nil, err
 				}
 
-				builder.WriteString(x)
+				builder.WriteRune(x)
 				i += 4
 			case 'U':
-				x, err := hexToString(token[i+1:len(token)-1], 8)
+				x, err := hexToRune(token[i+1:len(token)-1], 8)
 				if err != nil {
-					return nil, nil, err
+					return nil, nil, nil, err
 				}
 
-				builder.WriteString(x)
+				builder.WriteRune(x)
 				i += 8
 			default:
-				return nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
+				return nil, nil, nil, newDecodeError(token[i:i+1], "invalid escaped character %#U", c)
 			}
+			i++
 		} else {
-			builder.WriteByte(c)
+			size := utf8ValidNext(token[i:])
+			if size == 0 {
+				return nil, nil, nil, newDecodeError(token[i:i+1], "invalid character %#U", c)
+			}
+			builder.Write(token[i : i+size])
+			i += size
 		}
 	}
 
-	return builder.Bytes(), rest, nil
+	return token, builder.Bytes(), rest, nil
 }
 
-func hexToString(b []byte, length int) (string, error) {
+func hexToRune(b []byte, length int) (rune, error) {
 	if len(b) < length {
-		return "", newDecodeError(b, "unicode point needs %d character, not %d", length, len(b))
+		return -1, newDecodeError(b, "unicode point needs %d character, not %d", length, len(b))
 	}
 	b = b[:length]
 
-	//nolint:godox
-	// TODO: slow
-	intcode, err := strconv.ParseInt(string(b), 16, 32)
-	if err != nil {
-		return "", newDecodeError(b, "couldn't parse hexadecimal number: %w", err)
+	var r uint32
+	for i, c := range b {
+		d := uint32(0)
+		switch {
+		case '0' <= c && c <= '9':
+			d = uint32(c - '0')
+		case 'a' <= c && c <= 'f':
+			d = uint32(c - 'a' + 10)
+		case 'A' <= c && c <= 'F':
+			d = uint32(c - 'A' + 10)
+		default:
+			return -1, newDecodeError(b[i:i+1], "non-hex character")
+		}
+		r = r*16 + d
 	}
 
-	return string(rune(intcode)), nil
+	if r > unicode.MaxRune || 0xD800 <= r && r < 0xE000 {
+		return -1, newDecodeError(b, "escape sequence is invalid Unicode code point")
+	}
+
+	return rune(r), nil
 }
 
 func (p *parser) parseWhitespace(b []byte) []byte {
@@ -753,7 +854,7 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
 	switch b[0] {
 	case 'i':
 		if !scanFollowsInf(b) {
-			return ast.Reference{}, nil, newDecodeError(atmost(b, 3), "expected 'inf'")
+			return ast.InvalidReference, nil, newDecodeError(atmost(b, 3), "expected 'inf'")
 		}
 
 		return p.builder.Push(ast.Node{
@@ -762,7 +863,7 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
 		}), b[3:], nil
 	case 'n':
 		if !scanFollowsNan(b) {
-			return ast.Reference{}, nil, newDecodeError(atmost(b, 3), "expected 'nan'")
+			return ast.InvalidReference, nil, newDecodeError(atmost(b, 3), "expected 'nan'")
 		}
 
 		return p.builder.Push(ast.Node{
@@ -773,7 +874,6 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
 		return p.scanIntOrFloat(b)
 	}
 
-	//nolint:gomnd
 	if len(b) < 3 {
 		return p.scanIntOrFloat(b)
 	}
@@ -791,26 +891,17 @@ func (p *parser) parseIntOrFloatOrDateTime(b []byte) (ast.Reference, []byte, err
 		if idx == 2 && c == ':' || (idx == 4 && c == '-') {
 			return p.scanDateTime(b)
 		}
-	}
-
-	return p.scanIntOrFloat(b)
-}
 
-func digitsToInt(b []byte) int {
-	x := 0
-
-	for _, d := range b {
-		x *= 10
-		x += int(d - '0')
+		break
 	}
 
-	return x
+	return p.scanIntOrFloat(b)
 }
 
-//nolint:gocognit,cyclop
 func (p *parser) scanDateTime(b []byte) (ast.Reference, []byte, error) {
 	// scans for contiguous characters in [0-9T:Z.+-], and up to one space if
 	// followed by a digit.
+	hasDate := false
 	hasTime := false
 	hasTz := false
 	seenSpace := false
@@ -823,17 +914,23 @@ byteLoop:
 		switch {
 		case isDigit(c):
 		case c == '-':
-			const offsetOfTz = 19
-			if i == offsetOfTz {
+			hasDate = true
+			const minOffsetOfTz = 8
+			if i >= minOffsetOfTz {
 				hasTz = true
 			}
-		case c == 'T' || c == ':' || c == '.':
+		case c == 'T' || c == 't' || c == ':' || c == '.':
 			hasTime = true
-		case c == '+' || c == '-' || c == 'Z':
+		case c == '+' || c == '-' || c == 'Z' || c == 'z':
 			hasTz = true
 		case c == ' ':
 			if !seenSpace && i+1 < len(b) && isDigit(b[i+1]) {
 				i += 2
+				// Avoid reaching past the end of the document in case the time
+				// is malformed. See TestIssue585.
+				if i >= len(b) {
+					i--
+				}
 				seenSpace = true
 				hasTime = true
 			} else {
@@ -847,10 +944,14 @@ byteLoop:
 	var kind ast.Kind
 
 	if hasTime {
-		if hasTz {
-			kind = ast.DateTime
+		if hasDate {
+			if hasTz {
+				kind = ast.DateTime
+			} else {
+				kind = ast.LocalDateTime
+			}
 		} else {
-			kind = ast.LocalDateTime
+			kind = ast.LocalTime
 		}
 	} else {
 		kind = ast.LocalDate
@@ -866,7 +967,7 @@ byteLoop:
 func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
 	i := 0
 
-	if len(b) > 2 && b[0] == '0' && b[1] != '.' {
+	if len(b) > 2 && b[0] == '0' && b[1] != '.' && b[1] != 'e' && b[1] != 'E' {
 		var isValidRune validRuneFn
 
 		switch b[1] {
@@ -918,7 +1019,7 @@ func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
 				}), b[i+3:], nil
 			}
 
-			return ast.Reference{}, nil, newDecodeError(b[i:i+1], "unexpected character 'i' while scanning for a number")
+			return ast.InvalidReference, nil, newDecodeError(b[i:i+1], "unexpected character 'i' while scanning for a number")
 		}
 
 		if c == 'n' {
@@ -929,14 +1030,14 @@ func (p *parser) scanIntOrFloat(b []byte) (ast.Reference, []byte, error) {
 				}), b[i+3:], nil
 			}
 
-			return ast.Reference{}, nil, newDecodeError(b[i:i+1], "unexpected character 'n' while scanning for a number")
+			return ast.InvalidReference, nil, newDecodeError(b[i:i+1], "unexpected character 'n' while scanning for a number")
 		}
 
 		break
 	}
 
 	if i == 0 {
-		return ast.Reference{}, b, newDecodeError(b, "incomplete number")
+		return ast.InvalidReference, b, newDecodeError(b, "incomplete number")
 	}
 
 	kind := ast.Integer
@@ -973,8 +1074,12 @@ func isValidBinaryRune(r byte) bool {
 }
 
 func expect(x byte, b []byte) ([]byte, error) {
+	if len(b) == 0 {
+		return nil, newDecodeError(b, "expected character %c but the document ended here", x)
+	}
+
 	if b[0] != x {
-		return nil, newDecodeError(b[0:1], "expected character %U", x)
+		return nil, newDecodeError(b[0:1], "expected character %c", x)
 	}
 
 	return b[1:], nil
diff --git a/vendor/github.com/pelletier/go-toml/v2/scanner.go b/vendor/github.com/pelletier/go-toml/v2/scanner.go
index b20370223..bb445fab4 100644
--- a/vendor/github.com/pelletier/go-toml/v2/scanner.go
+++ b/vendor/github.com/pelletier/go-toml/v2/scanner.go
@@ -49,13 +49,18 @@ func scanLiteralString(b []byte) ([]byte, []byte, error) {
 	// literal-string = apostrophe *literal-char apostrophe
 	// apostrophe = %x27 ; ' apostrophe
 	// literal-char = %x09 / %x20-26 / %x28-7E / non-ascii
-	for i := 1; i < len(b); i++ {
+	for i := 1; i < len(b); {
 		switch b[i] {
 		case '\'':
 			return b[:i+1], b[i+1:], nil
-		case '\n':
+		case '\n', '\r':
 			return nil, nil, newDecodeError(b[i:i+1], "literal strings cannot have new lines")
 		}
+		size := utf8ValidNext(b[i:])
+		if size == 0 {
+			return nil, nil, newDecodeError(b[i:i+1], "invalid character")
+		}
+		i += size
 	}
 
 	return nil, nil, newDecodeError(b[len(b):], "unterminated literal string")
@@ -70,10 +75,49 @@ func scanMultilineLiteralString(b []byte) ([]byte, []byte, error) {
 	// mll-content = mll-char / newline
 	// mll-char = %x09 / %x20-26 / %x28-7E / non-ascii
 	// mll-quotes = 1*2apostrophe
-	for i := 3; i < len(b); i++ {
-		if b[i] == '\'' && scanFollowsMultilineLiteralStringDelimiter(b[i:]) {
-			return b[:i+3], b[i+3:], nil
+	for i := 3; i < len(b); {
+		switch b[i] {
+		case '\'':
+			if scanFollowsMultilineLiteralStringDelimiter(b[i:]) {
+				i += 3
+
+				// At that point we found 3 apostrophe, and i is the
+				// index of the byte after the third one. The scanner
+				// needs to be eager, because there can be an extra 2
+				// apostrophe that can be accepted at the end of the
+				// string.
+
+				if i >= len(b) || b[i] != '\'' {
+					return b[:i], b[i:], nil
+				}
+				i++
+
+				if i >= len(b) || b[i] != '\'' {
+					return b[:i], b[i:], nil
+				}
+				i++
+
+				if i < len(b) && b[i] == '\'' {
+					return nil, nil, newDecodeError(b[i-3:i+1], "''' not allowed in multiline literal string")
+				}
+
+				return b[:i], b[i:], nil
+			}
+		case '\r':
+			if len(b) < i+2 {
+				return nil, nil, newDecodeError(b[len(b):], `need a \n after \r`)
+			}
+			if b[i+1] != '\n' {
+				return nil, nil, newDecodeError(b[i:i+2], `need a \n after \r`)
+			}
+			i += 2 // skip the \n
+			continue
+		}
+		size := utf8ValidNext(b[i:])
+		if size == 0 {
+			return nil, nil, newDecodeError(b[i:i+1], "invalid character")
 		}
+		i += size
 	}
 
 	return nil, nil, newDecodeError(b[len(b):], `multiline literal string not terminated by '''`)
@@ -106,45 +150,62 @@ func scanWhitespace(b []byte) ([]byte, []byte) {
 }
 
 //nolint:unparam
-func scanComment(b []byte) ([]byte, []byte) {
+func scanComment(b []byte) ([]byte, []byte, error) {
 	// comment-start-symbol = %x23 ; #
 	// non-ascii = %x80-D7FF / %xE000-10FFFF
 	// non-eol = %x09 / %x20-7F / non-ascii
 	//
 	// comment = comment-start-symbol *non-eol
-	for i := 1; i < len(b); i++ {
+
+	for i := 1; i < len(b); {
 		if b[i] == '\n' {
-			return b[:i], b[i:]
+			return b[:i], b[i:], nil
 		}
+		if b[i] == '\r' {
+			if i+1 < len(b) && b[i+1] == '\n' {
+				return b[:i+1], b[i+1:], nil
+			}
+			return nil, nil, newDecodeError(b[i:i+1], "invalid character in comment")
+		}
+		size := utf8ValidNext(b[i:])
+		if size == 0 {
+			return nil, nil, newDecodeError(b[i:i+1], "invalid character in comment")
+		}
+
+		i += size
 	}
 
-	return b, nil
+	return b, b[len(b):], nil
 }
 
-func scanBasicString(b []byte) ([]byte, []byte, error) {
+func scanBasicString(b []byte) ([]byte, bool, []byte, error) {
 	// basic-string = quotation-mark *basic-char quotation-mark
 	// quotation-mark = %x22            ; "
 	// basic-char = basic-unescaped / escaped
 	// basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
 	// escaped = escape escape-seq-char
-	for i := 1; i < len(b); i++ {
+	escaped := false
+	i := 1
+
+	for ; i < len(b); i++ {
 		switch b[i] {
 		case '"':
-			return b[:i+1], b[i+1:], nil
-		case '\n':
-			return nil, nil, newDecodeError(b[i:i+1], "basic strings cannot have new lines")
+			return b[:i+1], escaped, b[i+1:], nil
+		case '\n', '\r':
+			return nil, escaped, nil, newDecodeError(b[i:i+1], "basic strings cannot have new lines")
 		case '\\':
 			if len(b) < i+2 {
-				return nil, nil, newDecodeError(b[i:i+1], "need a character after \\")
+				return nil, escaped, nil, newDecodeError(b[i:i+1], "need a character after \\")
 			}
+			escaped = true
 			i++ // skip the next character
 		}
 	}
 
-	return nil, nil, newDecodeError(b[len(b):], `basic string not terminated by "`)
+	return nil, escaped, nil, newDecodeError(b[len(b):], `basic string not terminated by "`)
 }
 
-func scanMultilineBasicString(b []byte) ([]byte, []byte, error) {
+func scanMultilineBasicString(b []byte) ([]byte, bool, []byte, error) {
 	// ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
 	// ml-basic-string-delim
 	// ml-basic-string-delim = 3quotation-mark
@@ -155,19 +216,54 @@ func scanMultilineBasicString(b []byte) ([]byte, []byte, error) {
 	// mlb-quotes = 1*2quotation-mark
 	// mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
 	// mlb-escaped-nl = escape ws newline *( wschar / newline )
-	for i := 3; i < len(b); i++ {
+
+	escaped := false
+	i := 3
+
+	for ; i < len(b); i++ {
 		switch b[i] {
 		case '"':
 			if scanFollowsMultilineBasicStringDelimiter(b[i:]) {
-				return b[:i+3], b[i+3:], nil
+				i += 3
+
+				// At that point we found 3 apostrophe, and i is the
+				// index of the byte after the third one. The scanner
+				// needs to be eager, because there can be an extra 2
+				// apostrophe that can be accepted at the end of the
+				// string.
+
+				if i >= len(b) || b[i] != '"' {
+					return b[:i], escaped, b[i:], nil
+				}
+				i++
+
+				if i >= len(b) || b[i] != '"' {
+					return b[:i], escaped, b[i:], nil
+				}
+				i++
+
+				if i < len(b) && b[i] == '"' {
+					return nil, escaped, nil, newDecodeError(b[i-3:i+1], `""" not allowed in multiline basic string`)
+				}
+
+				return b[:i], escaped, b[i:], nil
 			}
 		case '\\':
 			if len(b) < i+2 {
-				return nil, nil, newDecodeError(b[len(b):], "need a character after \\")
+				return nil, escaped, nil, newDecodeError(b[len(b):], "need a character after \\")
 			}
+			escaped = true
 			i++ // skip the next character
+		case '\r':
+			if len(b) < i+2 {
+				return nil, escaped, nil, newDecodeError(b[len(b):], `need a \n after \r`)
+			}
+			if b[i+1] != '\n' {
+				return nil, escaped, nil, newDecodeError(b[i:i+2], `need a \n after \r`)
+			}
+			i++ // skip the \n
 		}
 	}
 
-	return nil, nil, newDecodeError(b[len(b):], `multiline basic string not terminated by """`)
+	return nil, escaped, nil, newDecodeError(b[len(b):], `multiline basic string not terminated by """`)
 }
diff --git a/vendor/github.com/pelletier/go-toml/v2/strict.go b/vendor/github.com/pelletier/go-toml/v2/strict.go
index 2b2e7d652..b7830d139 100644
--- a/vendor/github.com/pelletier/go-toml/v2/strict.go
+++ b/vendor/github.com/pelletier/go-toml/v2/strict.go
@@ -2,6 +2,7 @@ package toml
 
 import (
 	"github.com/pelletier/go-toml/v2/internal/ast"
+	"github.com/pelletier/go-toml/v2/internal/danger"
 	"github.com/pelletier/go-toml/v2/internal/tracker"
 )
 
@@ -14,7 +15,7 @@ type strict struct {
 	missing []decodeError
 }
 
-func (s *strict) EnterTable(node ast.Node) {
+func (s *strict) EnterTable(node *ast.Node) {
 	if !s.Enabled {
 		return
 	}
@@ -22,7 +23,7 @@ func (s *strict) EnterTable(node ast.Node) {
 	s.key.UpdateTable(node)
 }
 
-func (s *strict) EnterArrayTable(node ast.Node) {
+func (s *strict) EnterArrayTable(node *ast.Node) {
 	if !s.Enabled {
 		return
 	}
@@ -30,7 +31,7 @@ func (s *strict) EnterArrayTable(node ast.Node) {
 	s.key.UpdateArrayTable(node)
 }
 
-func (s *strict) EnterKeyValue(node ast.Node) {
+func (s *strict) EnterKeyValue(node *ast.Node) {
 	if !s.Enabled {
 		return
 	}
@@ -38,7 +39,7 @@ func (s *strict) EnterKeyValue(node ast.Node) {
 	s.key.Push(node)
 }
 
-func (s *strict) ExitKeyValue(node ast.Node) {
+func (s *strict) ExitKeyValue(node *ast.Node) {
 	if !s.Enabled {
 		return
 	}
@@ -46,7 +47,7 @@ func (s *strict) ExitKeyValue(node ast.Node) {
 	s.key.Pop(node)
 }
 
-func (s *strict) MissingTable(node ast.Node) {
+func (s *strict) MissingTable(node *ast.Node) {
 	if !s.Enabled {
 		return
 	}
@@ -58,7 +59,7 @@ func (s *strict) MissingTable(node ast.Node) {
 	})
 }
 
-func (s *strict) MissingField(node ast.Node) {
+func (s *strict) MissingField(node *ast.Node) {
 	if !s.Enabled {
 		return
 	}
@@ -86,3 +87,21 @@ func (s *strict) Error(doc []byte) error {
 
 	return err
 }
+
+func keyLocation(node *ast.Node) []byte {
+	k := node.Key()
+
+	hasOne := k.Next()
+	if !hasOne {
+		panic("should not be called with empty key")
+	}
+
+	start := k.Node().Data
+	end := k.Node().Data
+
+	for k.Next() {
+		end = k.Node().Data
+	}
+
+	return danger.BytesRange(start, end)
+}
diff --git a/vendor/github.com/pelletier/go-toml/v2/targets.go b/vendor/github.com/pelletier/go-toml/v2/targets.go
deleted file mode 100644
index 370892f0d..000000000
--- a/vendor/github.com/pelletier/go-toml/v2/targets.go
+++ /dev/null
@@ -1,536 +0,0 @@
-package toml
-
-import (
-	"fmt"
-	"math"
-	"reflect"
-	"strings"
-	"sync"
-)
-
-type target interface {
-	// Dereferences the target.
-	get() reflect.Value
-
-	// Store a string at the target.
-	setString(v string)
-
-	// Store a boolean at the target
-	setBool(v bool)
-
-	// Store an int64 at the target
-	setInt64(v int64)
-
-	// Store a float64 at the target
-	setFloat64(v float64)
-
-	// Stores any value at the target
-	set(v reflect.Value)
-}
-
-// valueTarget just contains a reflect.Value that can be set.
-// It is used for struct fields.
-type valueTarget reflect.Value
-
-func (t valueTarget) get() reflect.Value {
-	return reflect.Value(t)
-}
-
-func (t valueTarget) set(v reflect.Value) {
-	reflect.Value(t).Set(v)
-}
-
-func (t valueTarget) setString(v string) {
-	t.get().SetString(v)
-}
-
-func (t valueTarget) setBool(v bool) {
-	t.get().SetBool(v)
-}
-
-func (t valueTarget) setInt64(v int64) {
-	t.get().SetInt(v)
-}
-
-func (t valueTarget) setFloat64(v float64) {
-	t.get().SetFloat(v)
-}
-
-// interfaceTarget wraps an other target to dereference on get.
-type interfaceTarget struct {
-	x target
-}
-
-func (t interfaceTarget) get() reflect.Value {
-	return t.x.get().Elem()
-}
-
-func (t interfaceTarget) set(v reflect.Value) {
-	t.x.set(v)
-}
-
-func (t interfaceTarget) setString(v string) {
-	panic("interface targets should always go through set")
-}
-
-func (t interfaceTarget) setBool(v bool) {
-	panic("interface targets should always go through set")
-}
-
-func (t interfaceTarget) setInt64(v int64) {
-	panic("interface targets should always go through set")
-}
-
-func (t interfaceTarget) setFloat64(v float64) {
-	panic("interface targets should always go through set")
-}
-
-// mapTarget targets a specific key of a map.
-type mapTarget struct {
-	v reflect.Value
-	k reflect.Value
-}
-
-func (t mapTarget) get() reflect.Value {
-	return t.v.MapIndex(t.k)
-}
-
-func (t mapTarget) set(v reflect.Value) {
-	t.v.SetMapIndex(t.k, v)
-}
-
-func (t mapTarget) setString(v string) {
-	t.set(reflect.ValueOf(v))
-}
-
-func (t mapTarget) setBool(v bool) {
-	t.set(reflect.ValueOf(v))
-}
-
-func (t mapTarget) setInt64(v int64) {
-	t.set(reflect.ValueOf(v))
-}
-
-func (t mapTarget) setFloat64(v float64) {
-	t.set(reflect.ValueOf(v))
-}
-
-// makes sure that the value pointed at by t is indexable (Slice, Array), or
-// dereferences to an indexable (Ptr, Interface).
-func ensureValueIndexable(t target) error {
-	f := t.get()
-
-	switch f.Type().Kind() {
-	case reflect.Slice:
-		if f.IsNil() {
-			t.set(reflect.MakeSlice(f.Type(), 0, 0))
-			return nil
-		}
-	case reflect.Interface:
-		if f.IsNil() || f.Elem().Type() != sliceInterfaceType {
-			t.set(reflect.MakeSlice(sliceInterfaceType, 0, 0))
-			return nil
-		}
-	case reflect.Ptr:
-		panic("pointer should have already been dereferenced")
-	case reflect.Array:
-		// arrays are always initialized.
-	default:
-		return fmt.Errorf("toml: cannot store array in a %s", f.Kind())
-	}
-
-	return nil
-}
-
-var (
-	sliceInterfaceType     = reflect.TypeOf([]interface{}{})
-	mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
-)
-
-func ensureMapIfInterface(x target) {
-	v := x.get()
-
-	if v.Kind() == reflect.Interface && v.IsNil() {
-		newElement := reflect.MakeMap(mapStringInterfaceType)
-
-		x.set(newElement)
-	}
-}
-
-func setString(t target, v string) error {
-	f := t.get()
-
-	switch f.Kind() {
-	case reflect.String:
-		t.setString(v)
-	case reflect.Interface:
-		t.set(reflect.ValueOf(v))
-	default:
-		return fmt.Errorf("toml: cannot assign string to a %s", f.Kind())
-	}
-
-	return nil
-}
-
-func setBool(t target, v bool) error {
-	f := t.get()
-
-	switch f.Kind() {
-	case reflect.Bool:
-		t.setBool(v)
-	case reflect.Interface:
-		t.set(reflect.ValueOf(v))
-	default:
-		return fmt.Errorf("toml: cannot assign boolean to a %s", f.Kind())
-	}
-
-	return nil
-}
-
-const (
-	maxInt = int64(^uint(0) >> 1)
-	minInt = -maxInt - 1
-)
-
-//nolint:funlen,gocognit,cyclop
-func setInt64(t target, v int64) error {
-	f := t.get()
-
-	switch f.Kind() {
-	case reflect.Int64:
-		t.setInt64(v)
-	case reflect.Int32:
-		if v < math.MinInt32 || v > math.MaxInt32 {
-			return fmt.Errorf("toml: number %d does not fit in an int32", v)
-		}
-
-		t.set(reflect.ValueOf(int32(v)))
-		return nil
-	case reflect.Int16:
-		if v < math.MinInt16 || v > math.MaxInt16 {
-			return fmt.Errorf("toml: number %d does not fit in an int16", v)
-		}
-
-		t.set(reflect.ValueOf(int16(v)))
-	case reflect.Int8:
-		if v < math.MinInt8 || v > math.MaxInt8 {
-			return fmt.Errorf("toml: number %d does not fit in an int8", v)
-		}
-
-		t.set(reflect.ValueOf(int8(v)))
-	case reflect.Int:
-		if v < minInt || v > maxInt {
-			return fmt.Errorf("toml: number %d does not fit in an int", v)
-		}
-
-		t.set(reflect.ValueOf(int(v)))
-	case reflect.Uint64:
-		if v < 0 {
-			return fmt.Errorf("toml: negative number %d does not fit in an uint64", v)
-		}
-
-		t.set(reflect.ValueOf(uint64(v)))
-	case reflect.Uint32:
-		if v < 0 || v > math.MaxUint32 {
-			return fmt.Errorf("toml: negative number %d does not fit in an uint32", v)
-		}
-
-		t.set(reflect.ValueOf(uint32(v)))
-	case reflect.Uint16:
-		if v < 0 || v > math.MaxUint16 {
-			return fmt.Errorf("toml: negative number %d does not fit in an uint16", v)
-		}
-
-		t.set(reflect.ValueOf(uint16(v)))
-	case reflect.Uint8:
-		if v < 0 || v > math.MaxUint8 {
-			return fmt.Errorf("toml: negative number %d does not fit in an uint8", v)
-		}
-
-		t.set(reflect.ValueOf(uint8(v)))
-	case reflect.Uint:
-		if v < 0 {
-			return fmt.Errorf("toml: negative number %d does not fit in an uint", v)
-		}
-
-		t.set(reflect.ValueOf(uint(v)))
-	case reflect.Interface:
-		t.set(reflect.ValueOf(v))
-	default:
-		return fmt.Errorf("toml: integer cannot be assigned to %s", f.Kind())
-	}
-
-	return nil
-}
-
-func setFloat64(t target, v float64) error {
-	f := t.get()
-
-	switch f.Kind() {
-	case reflect.Float64:
-		t.setFloat64(v)
-	case reflect.Float32:
-		if v > math.MaxFloat32 {
-			return fmt.Errorf("toml: number %f does not fit in a float32", v)
-		}
-
-		t.set(reflect.ValueOf(float32(v)))
-	case reflect.Interface:
-		t.set(reflect.ValueOf(v))
-	default:
-		return fmt.Errorf("toml: float cannot be assigned to %s", f.Kind())
-	}
-
-	return nil
-}
-
-// Returns the element at idx of the value pointed at by target, or an error if
-// t does not point to an indexable.
-// If the target points to an Array and idx is out of bounds, it returns
-// (nil, nil) as this is not a fatal error (the unmarshaler will skip).
-func elementAt(t target, idx int) target {
-	f := t.get()
-
-	switch f.Kind() {
-	case reflect.Slice:
-		//nolint:godox
-		// TODO: use the idx function argument and avoid alloc if possible.
-		idx := f.Len()
-
-		t.set(reflect.Append(f, reflect.New(f.Type().Elem()).Elem()))
-
-		return valueTarget(t.get().Index(idx))
-	case reflect.Array:
-		if idx >= f.Len() {
-			return nil
-		}
-
-		return valueTarget(f.Index(idx))
-	case reflect.Interface:
-		// This function is called after ensureValueIndexable, so it's
-		// guaranteed that f contains an initialized slice.
-		ifaceElem := f.Elem()
-		idx := ifaceElem.Len()
-		newElem := reflect.New(ifaceElem.Type().Elem()).Elem()
-		newSlice := reflect.Append(ifaceElem, newElem)
-
-		t.set(newSlice)
-
-		return valueTarget(t.get().Elem().Index(idx))
-	default:
-		// Why ensureValueIndexable let it go through?
-		panic(fmt.Errorf("elementAt received unhandled value type: %s", f.Kind()))
-	}
-}
-
-func (d *decoder) scopeTableTarget(shouldAppend bool, t target, name string) (target, bool, error) {
-	x := t.get()
-
-	switch x.Kind() {
-	// Kinds that need to recurse
-	case reflect.Interface:
-		t := scopeInterface(shouldAppend, t)
-		return d.scopeTableTarget(shouldAppend, t, name)
-	case reflect.Ptr:
-		t := scopePtr(t)
-		return d.scopeTableTarget(shouldAppend, t, name)
-	case reflect.Slice:
-		t := scopeSlice(shouldAppend, t)
-		shouldAppend = false
-		return d.scopeTableTarget(shouldAppend, t, name)
-	case reflect.Array:
-		t, err := d.scopeArray(shouldAppend, t)
-		if err != nil {
-			return t, false, err
-		}
-		shouldAppend = false
-
-		return d.scopeTableTarget(shouldAppend, t, name)
-
-	// Terminal kinds
-	case reflect.Struct:
-		return scopeStruct(x, name)
-	case reflect.Map:
-		if x.IsNil() {
-			t.set(reflect.MakeMap(x.Type()))
-			x = t.get()
-		}
-
-		return scopeMap(x, name)
-	default:
-		panic(fmt.Sprintf("can't scope on a %s", x.Kind()))
-	}
-}
-
-func scopeInterface(shouldAppend bool, t target) target {
-	initInterface(shouldAppend, t)
-	return interfaceTarget{t}
-}
-
-func scopePtr(t target) target {
-	initPtr(t)
-	return valueTarget(t.get().Elem())
-}
-
-func initPtr(t target) {
-	x := t.get()
-	if !x.IsNil() {
-		return
-	}
-
-	t.set(reflect.New(x.Type().Elem()))
-}
-
-// initInterface makes sure that the interface pointed at by the target is not
-// nil.
-// Returns the target to the initialized value of the target.
-func initInterface(shouldAppend bool, t target) {
-	x := t.get()
-
-	if x.Kind() != reflect.Interface {
-		panic("this should only be called on interfaces")
-	}
-
-	if !x.IsNil() && (x.Elem().Type() == sliceInterfaceType || x.Elem().Type() == mapStringInterfaceType) {
-		return
-	}
-
-	var newElement reflect.Value
-	if shouldAppend {
-		newElement = reflect.MakeSlice(sliceInterfaceType, 0, 0)
-	} else {
-		newElement = reflect.MakeMap(mapStringInterfaceType)
-	}
-
-	t.set(newElement)
-}
-
-func scopeSlice(shouldAppend bool, t target) target {
-	v := t.get()
-
-	if shouldAppend {
-		newElem := reflect.New(v.Type().Elem())
-		newSlice := reflect.Append(v, newElem.Elem())
-
-		t.set(newSlice)
-
-		v = t.get()
-	}
-
-	return valueTarget(v.Index(v.Len() - 1))
-}
-
-func (d *decoder) scopeArray(shouldAppend bool, t target) (target, error) {
-	v := t.get()
-
-	idx := d.arrayIndex(shouldAppend, v)
-
-	if idx >= v.Len() {
-		return nil, fmt.Errorf("toml: impossible to insert element beyond array's size: %d", v.Len())
-	}
-
-	return valueTarget(v.Index(idx)), nil
-}
-
-func scopeMap(v reflect.Value, name string) (target, bool, error) {
-	k := reflect.ValueOf(name)
-
-	keyType := v.Type().Key()
-	if !k.Type().AssignableTo(keyType) {
-		if !k.Type().ConvertibleTo(keyType) {
-			return nil, false, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", k.Type(), keyType)
-		}
-
-		k = k.Convert(keyType)
-	}
-
-	if !v.MapIndex(k).IsValid() {
-		newElem := reflect.New(v.Type().Elem())
-		v.SetMapIndex(k, newElem.Elem())
-	}
-
-	return mapTarget{
-		v: v,
-		k: k,
-	}, true, nil
-}
-
-type fieldPathsMap = map[string][]int
-
-type fieldPathsCache struct {
-	m map[reflect.Type]fieldPathsMap
-	l sync.RWMutex
-}
-
-func (c *fieldPathsCache) get(t reflect.Type) (fieldPathsMap, bool) {
-	c.l.RLock()
-	paths, ok := c.m[t]
-	c.l.RUnlock()
-
-	return paths, ok
-}
-
-func (c *fieldPathsCache) set(t reflect.Type, m fieldPathsMap) {
-	c.l.Lock()
-	c.m[t] = m
-	c.l.Unlock()
-}
-
-var globalFieldPathsCache = fieldPathsCache{
-	m: map[reflect.Type]fieldPathsMap{},
-	l: sync.RWMutex{},
-}
-
-func scopeStruct(v reflect.Value, name string) (target, bool, error) {
-	//nolint:godox
-	// TODO: cache this, and reduce allocations
-	fieldPaths, ok := globalFieldPathsCache.get(v.Type())
-	if !ok {
-		fieldPaths = map[string][]int{}
-
-		path := make([]int, 0, 16)
-
-		var walk func(reflect.Value)
-		walk = func(v reflect.Value) {
-			t := v.Type()
-			for i := 0; i < t.NumField(); i++ {
-				l := len(path)
-				path = append(path, i)
-				f := t.Field(i)
-
-				if f.Anonymous {
-					walk(v.Field(i))
-				} else if f.PkgPath == "" {
-					// only consider exported fields
-					fieldName, ok := f.Tag.Lookup("toml")
-					if !ok {
-						fieldName = f.Name
-					}
-
-					pathCopy := make([]int, len(path))
-					copy(pathCopy, path)
-
-					fieldPaths[fieldName] = pathCopy
-					// extra copy for the case-insensitive match
-					fieldPaths[strings.ToLower(fieldName)] = pathCopy
-				}
-				path = path[:l]
-			}
-		}
-
-		walk(v)
-
-		globalFieldPathsCache.set(v.Type(), fieldPaths)
-	}
-
-	path, ok := fieldPaths[name]
-	if !ok {
-		path, ok = fieldPaths[strings.ToLower(name)]
-	}
-
-	if !ok {
-		return nil, false, nil
-	}
-
-	return valueTarget(v.FieldByIndex(path)), true, nil
-}
diff --git a/vendor/github.com/pelletier/go-toml/v2/types.go b/vendor/github.com/pelletier/go-toml/v2/types.go
new file mode 100644
index 000000000..630a45466
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/types.go
@@ -0,0 +1,14 @@
+package toml
+
+import (
+	"encoding"
+	"reflect"
+	"time"
+)
+
+var timeType = reflect.TypeOf(time.Time{})
+var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem()
+var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
+var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}{})
+var sliceInterfaceType = reflect.TypeOf([]interface{}{})
+var stringType = reflect.TypeOf("")
diff --git a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
index 6a156ae6a..d0d7a72d0 100644
--- a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
+++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
@@ -6,12 +6,15 @@ import (
 	"fmt"
 	"io"
 	"io/ioutil"
+	"math"
 	"reflect"
+	"strings"
+	"sync/atomic"
 	"time"
 
 	"github.com/pelletier/go-toml/v2/internal/ast"
+	"github.com/pelletier/go-toml/v2/internal/danger"
 	"github.com/pelletier/go-toml/v2/internal/tracker"
-	"github.com/pelletier/go-toml/v2/internal/unsafe"
 )
 
 // Unmarshal deserializes a TOML document into a Go value.
@@ -20,9 +23,9 @@ import (
 func Unmarshal(data []byte, v interface{}) error {
 	p := parser{}
 	p.Reset(data)
-	d := decoder{}
+	d := decoder{p: &p}
 
-	return d.FromParser(&p, v)
+	return d.FromParser(v)
 }
 
 // Decoder reads and decode a TOML document from an input stream.
@@ -39,24 +42,27 @@ func NewDecoder(r io.Reader) *Decoder {
 	return &Decoder{r: r}
 }
 
-// SetStrict toggles decoding in stict mode.
+// DisallowUnknownFields causes the Decoder to return an error when the
+// destination is a struct and the input contains a key that does not match a
+// non-ignored field.
 //
-// When the decoder is in strict mode, it will record fields from the document
-// that could not be set on the target value. In that case, the decoder returns
-// a StrictMissingError that can be used to retrieve the individual errors as
-// well as generate a human readable description of the missing fields.
-func (d *Decoder) SetStrict(strict bool) {
-	d.strict = strict
+// In that case, the Decoder returns a StrictMissingError that can be used to
+// retrieve the individual errors as well as generate a human readable
+// description of the missing fields.
+func (d *Decoder) DisallowUnknownFields() *Decoder {
+	d.strict = true
+	return d
 }
 
 // Decode the whole content of r into v.
 //
 // By default, values in the document that don't exist in the target Go value
-// are ignored. See Decoder.SetStrict() to change this behavior.
+// are ignored. See Decoder.DisallowUnknownFields() to change this behavior.
 //
 // When a TOML local date, time, or date-time is decoded into a time.Time, its
 // value is represented in time.Local timezone. Otherwise the approriate Local*
-// structure is used.
+// structure is used. For time values, precision up to the nanosecond is
+// supported by truncating extra digits.
 //
 // Empty tables decoded in an interface{} create an empty initialized
 // map[string]interface{}.
@@ -68,22 +74,27 @@ func (d *Decoder) SetStrict(strict bool) {
 // bounds for the target type (which includes negative numbers when decoding
 // into an unsigned int).
 //
-// Type mapping
+// If an error occurs while decoding the content of the document, this function
+// returns a toml.DecodeError, providing context about the issue. When using
+// strict mode and a field is missing, a `toml.StrictMissingError` is
+// returned. In any other case, this function returns a standard Go error.
+//
+// # Type mapping
 //
 // List of supported TOML types and their associated accepted Go types:
 //
-//   String           -> string
-//   Integer          -> uint*, int*, depending on size
-//   Float            -> float*, depending on size
-//   Boolean          -> bool
-//   Offset Date-Time -> time.Time
-//   Local Date-time  -> LocalDateTime, time.Time
-//   Local Date       -> LocalDate, time.Time
-//   Local Time       -> LocalTime, time.Time
-//   Array            -> slice and array, depending on elements types
-//   Table            -> map and struct
-//   Inline Table     -> same as Table
-//   Array of Tables  -> same as Array and Table
+//	String           -> string
+//	Integer          -> uint*, int*, depending on size
+//	Float            -> float*, depending on size
+//	Boolean          -> bool
+//	Offset Date-Time -> time.Time
+//	Local Date-time  -> LocalDateTime, time.Time
+//	Local Date       -> LocalDate, time.Time
+//	Local Time       -> LocalTime, time.Time
+//	Array            -> slice and array, depending on elements types
+//	Table            -> map and struct
+//	Inline Table     -> same as Table
+//	Array of Tables  -> same as Array and Table
 func (d *Decoder) Decode(v interface{}) error {
 	b, err := ioutil.ReadAll(d.r)
 	if err != nil {
@@ -93,16 +104,33 @@ func (d *Decoder) Decode(v interface{}) error {
 	p := parser{}
 	p.Reset(b)
 	dec := decoder{
+		p: &p,
 		strict: strict{
 			Enabled: d.strict,
 		},
 	}
 
-	return dec.FromParser(&p, v)
+	return dec.FromParser(v)
 }
 
 type decoder struct {
+	// Which parser instance in use for this decoding session.
+	p *parser
+
+	// Flag indicating that the current expression is stashed.
+	// If set to true, calling nextExpr will not actually pull a new expression
+	// but turn off the flag instead.
+	stashedExpr bool
+
+	// Skip expressions until a table is found. This is set to true when a
+	// table could not be created (missing field in map), so all KV expressions
+	// need to be skipped.
+	skipUntilTable bool
+
 	// Tracks position in Go arrays.
+	// This is used when decoding [[array tables]] into Go arrays. Given array
+	// tables are separate TOML expression, we need to keep track of where we
+	// are at in the Go array, as we can't just introspect its size.
 	arrayIndexes map[reflect.Value]int
 
 	// Tracks keys that have been seen, with which type.
@@ -110,6 +138,39 @@ type decoder struct {
 
 	// Strict mode
 	strict strict
+
+	// Current context for the error.
+	errorContext *errorContext
+}
+
+type errorContext struct {
+	Struct reflect.Type
+	Field  []int
+}
+
+func (d *decoder) typeMismatchError(toml string, target reflect.Type) error {
+	if d.errorContext != nil && d.errorContext.Struct != nil {
+		ctx := d.errorContext
+		f := ctx.Struct.FieldByIndex(ctx.Field)
+		return fmt.Errorf("toml: cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type)
+	}
+	return fmt.Errorf("toml: cannot decode TOML %s into a Go value of type %s", toml, target)
+}
+
+func (d *decoder) expr() *ast.Node {
+	return d.p.Expression()
+}
+
+func (d *decoder) nextExpr() bool {
+	if d.stashedExpr {
+		d.stashedExpr = false
+		return true
+	}
+	return d.p.NextExpression()
+}
+
+func (d *decoder) stashExpr() {
+	d.stashedExpr = true
 }
 
 func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int {
@@ -129,236 +190,430 @@ func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int {
 	return idx
 }
 
-func (d *decoder) FromParser(p *parser, v interface{}) error {
-	err := d.fromParser(p, v)
+func (d *decoder) FromParser(v interface{}) error {
+	r := reflect.ValueOf(v)
+	if r.Kind() != reflect.Ptr {
+		return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())
+	}
+
+	if r.IsNil() {
+		return fmt.Errorf("toml: decoding pointer target cannot be nil")
+	}
+
+	r = r.Elem()
+	if r.Kind() == reflect.Interface && r.IsNil() {
+		newMap := map[string]interface{}{}
+		r.Set(reflect.ValueOf(newMap))
+	}
+
+	err := d.fromParser(r)
 	if err == nil {
-		return d.strict.Error(p.data)
+		return d.strict.Error(d.p.data)
 	}
 
 	var e *decodeError
 	if errors.As(err, &e) {
-		return wrapDecodeError(p.data, e)
+		return wrapDecodeError(d.p.data, e)
 	}
 
 	return err
 }
 
-func keyLocation(node ast.Node) []byte {
-	k := node.Key()
-
-	hasOne := k.Next()
-	if !hasOne {
-		panic("should not be called with empty key")
+func (d *decoder) fromParser(root reflect.Value) error {
+	for d.nextExpr() {
+		err := d.handleRootExpression(d.expr(), root)
+		if err != nil {
+			return err
+		}
 	}
 
-	start := k.Node().Data
-	end := k.Node().Data
+	return d.p.Error()
+}
+
+/*
+Rules for the unmarshal code:
 
-	for k.Next() {
-		end = k.Node().Data
-	}
+- The stack is used to keep track of which values need to be set where.
+- handle* functions <=> switch on a given ast.Kind.
+- unmarshalX* functions need to unmarshal a node of kind X.
+- An "object" is either a struct or a map.
+*/
 
-	return unsafe.BytesRange(start, end)
-}
+func (d *decoder) handleRootExpression(expr *ast.Node, v reflect.Value) error {
+	var x reflect.Value
+	var err error
 
-//nolint:funlen,cyclop
-func (d *decoder) fromParser(p *parser, v interface{}) error {
-	r := reflect.ValueOf(v)
-	if r.Kind() != reflect.Ptr {
-		return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind())
+	if !(d.skipUntilTable && expr.Kind == ast.KeyValue) {
+		err = d.seen.CheckExpression(expr)
+		if err != nil {
+			return err
+		}
 	}
 
-	if r.IsNil() {
-		return fmt.Errorf("toml: decoding pointer target cannot be nil")
+	switch expr.Kind {
+	case ast.KeyValue:
+		if d.skipUntilTable {
+			return nil
+		}
+		x, err = d.handleKeyValue(expr, v)
+	case ast.Table:
+		d.skipUntilTable = false
+		d.strict.EnterTable(expr)
+		x, err = d.handleTable(expr.Key(), v)
+	case ast.ArrayTable:
+		d.skipUntilTable = false
+		d.strict.EnterArrayTable(expr)
+		x, err = d.handleArrayTable(expr.Key(), v)
+	default:
+		panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind))
 	}
 
-	var (
-		skipUntilTable bool
-		root           target = valueTarget(r.Elem())
-	)
+	if d.skipUntilTable {
+		if expr.Kind == ast.Table || expr.Kind == ast.ArrayTable {
+			d.strict.MissingTable(expr)
+		}
+	} else if err == nil && x.IsValid() {
+		v.Set(x)
+	}
 
-	current := root
+	return err
+}
 
-	for p.NextExpression() {
-		node := p.Expression()
+func (d *decoder) handleArrayTable(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	if key.Next() {
+		return d.handleArrayTablePart(key, v)
+	}
+	return d.handleKeyValues(v)
+}
 
-		if node.Kind == ast.KeyValue && skipUntilTable {
-			continue
+func (d *decoder) handleArrayTableCollectionLast(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	switch v.Kind() {
+	case reflect.Interface:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			elem = reflect.New(sliceInterfaceType).Elem()
+			elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+		} else if elem.Kind() == reflect.Slice {
+			if elem.Type() != sliceInterfaceType {
+				elem = reflect.New(sliceInterfaceType).Elem()
+				elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+			} else if !elem.CanSet() {
+				nelem := reflect.New(sliceInterfaceType).Elem()
+				nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
+				reflect.Copy(nelem, elem)
+				elem = nelem
+			}
+		}
+		return d.handleArrayTableCollectionLast(key, elem)
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			ptr := reflect.New(v.Type().Elem())
+			v.Set(ptr)
+			elem = ptr.Elem()
 		}
 
-		err := d.seen.CheckExpression(node)
+		elem, err := d.handleArrayTableCollectionLast(key, elem)
 		if err != nil {
-			return err
+			return reflect.Value{}, err
 		}
+		v.Elem().Set(elem)
 
-		var found bool
+		return v, nil
+	case reflect.Slice:
+		elemType := v.Type().Elem()
+		var elem reflect.Value
+		if elemType.Kind() == reflect.Interface {
+			elem = makeMapStringInterface()
+		} else {
+			elem = reflect.New(elemType).Elem()
+		}
+		elem2, err := d.handleArrayTable(key, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if elem2.IsValid() {
+			elem = elem2
+		}
+		return reflect.Append(v, elem), nil
+	case reflect.Array:
+		idx := d.arrayIndex(true, v)
+		if idx >= v.Len() {
+			return v, fmt.Errorf("toml: cannot decode array table into %s at position %d", v.Type(), idx)
+		}
+		elem := v.Index(idx)
+		_, err := d.handleArrayTable(key, elem)
+		return v, err
+	default:
+		return reflect.Value{}, fmt.Errorf("toml: cannot decode array table into a %s", v.Type())
+	}
+}
 
-		switch node.Kind {
-		case ast.KeyValue:
-			err = d.unmarshalKeyValue(current, node)
-			found = true
-		case ast.Table:
-			d.strict.EnterTable(node)
+// When parsing an array table expression, each part of the key needs to be
+// evaluated like a normal key, but if it returns a collection, it also needs to
+// point to the last element of the collection. Unless it is the last part of
+// the key, then it needs to create a new element at the end.
+func (d *decoder) handleArrayTableCollection(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	if key.IsLast() {
+		return d.handleArrayTableCollectionLast(key, v)
+	}
 
-			current, found, err = d.scopeWithKey(root, node.Key())
-			if err == nil && found {
-				// In case this table points to an interface,
-				// make sure it at least holds something that
-				// looks like a table. Otherwise the information
-				// of a table is lost, and marshal cannot do the
-				// round trip.
-				ensureMapIfInterface(current)
-			}
-		case ast.ArrayTable:
-			d.strict.EnterArrayTable(node)
-			current, found, err = d.scopeWithArrayTable(root, node.Key())
-		default:
-			panic(fmt.Sprintf("this should not be a top level node type: %s", node.Kind))
+	switch v.Kind() {
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			ptr := reflect.New(v.Type().Elem())
+			v.Set(ptr)
+			elem = ptr.Elem()
 		}
 
+		elem, err := d.handleArrayTableCollection(key, elem)
 		if err != nil {
-			return err
+			return reflect.Value{}, err
+		}
+		if elem.IsValid() {
+			v.Elem().Set(elem)
 		}
 
-		if !found {
-			skipUntilTable = true
+		return v, nil
+	case reflect.Slice:
+		elem := v.Index(v.Len() - 1)
+		x, err := d.handleArrayTable(key, elem)
+		if err != nil || d.skipUntilTable {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			elem.Set(x)
+		}
 
-			d.strict.MissingTable(node)
+		return v, err
+	case reflect.Array:
+		idx := d.arrayIndex(false, v)
+		if idx >= v.Len() {
+			return v, fmt.Errorf("toml: cannot decode array table into %s at position %d", v.Type(), idx)
 		}
+		elem := v.Index(idx)
+		_, err := d.handleArrayTable(key, elem)
+		return v, err
 	}
 
-	return p.Error()
+	return d.handleArrayTable(key, v)
 }
 
-// scopeWithKey performs target scoping when unmarshaling an ast.KeyValue node.
-//
-// The goal is to hop from target to target recursively using the names in key.
-// Parts of the key should be used to resolve field names for structs, and as
-// keys when targeting maps.
-//
-// When encountering slices, it should always use its last element, and error
-// if the slice does not have any.
-func (d *decoder) scopeWithKey(x target, key ast.Iterator) (target, bool, error) {
-	var (
-		err   error
-		found bool
-	)
+func (d *decoder) handleKeyPart(key ast.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) {
+	var rv reflect.Value
 
-	for key.Next() {
-		n := key.Node()
+	// First, dispatch over v to make sure it is a valid object.
+	// There is no guarantee over what it could be.
+	switch v.Kind() {
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			v.Set(reflect.New(v.Type().Elem()))
+		}
+		elem = v.Elem()
+		return d.handleKeyPart(key, elem, nextFn, makeFn)
+	case reflect.Map:
+		vt := v.Type()
+
+		// Create the key for the map element. Convert to key type.
+		mk := reflect.ValueOf(string(key.Node().Data)).Convert(vt.Key())
+
+		// If the map does not exist, create it.
+		if v.IsNil() {
+			vt := v.Type()
+			v = reflect.MakeMap(vt)
+			rv = v
+		}
 
-		x, found, err = d.scopeTableTarget(false, x, string(n.Data))
-		if err != nil || !found {
-			return nil, found, err
+		mv := v.MapIndex(mk)
+		set := false
+		if !mv.IsValid() {
+			// If there is no value in the map, create a new one according to
+			// the map type. If the element type is interface, create either a
+			// map[string]interface{} or a []interface{} depending on whether
+			// this is the last part of the array table key.
+
+			t := vt.Elem()
+			if t.Kind() == reflect.Interface {
+				mv = makeFn()
+			} else {
+				mv = reflect.New(t).Elem()
+			}
+			set = true
+		} else if mv.Kind() == reflect.Interface {
+			mv = mv.Elem()
+			if !mv.IsValid() {
+				mv = makeFn()
+			}
+			set = true
+		} else if !mv.CanAddr() {
+			vt := v.Type()
+			t := vt.Elem()
+			oldmv := mv
+			mv = reflect.New(t).Elem()
+			mv.Set(oldmv)
+			set = true
 		}
-	}
 
-	return x, true, nil
-}
+		x, err := nextFn(key, mv)
+		if err != nil {
+			return reflect.Value{}, err
+		}
 
-//nolint:cyclop
-// scopeWithArrayTable performs target scoping when unmarshaling an
-// ast.ArrayTable node.
-//
-// It is the same as scopeWithKey, but when scoping the last part of the key
-// it creates a new element in the array instead of using the last one.
-func (d *decoder) scopeWithArrayTable(x target, key ast.Iterator) (target, bool, error) {
-	var (
-		err   error
-		found bool
-	)
-
-	for key.Next() {
-		n := key.Node()
-		if !n.Next().Valid() { // want to stop at one before last
-			break
+		if x.IsValid() {
+			mv = x
+			set = true
 		}
 
-		x, found, err = d.scopeTableTarget(false, x, string(n.Data))
-		if err != nil || !found {
-			return nil, found, err
+		if set {
+			v.SetMapIndex(mk, mv)
+		}
+	case reflect.Struct:
+		path, found := structFieldPath(v, string(key.Node().Data))
+		if !found {
+			d.skipUntilTable = true
+			return reflect.Value{}, nil
 		}
-	}
 
-	n := key.Node()
+		if d.errorContext == nil {
+			d.errorContext = new(errorContext)
+		}
+		t := v.Type()
+		d.errorContext.Struct = t
+		d.errorContext.Field = path
+
+		f := fieldByIndex(v, path)
+		x, err := nextFn(key, f)
+		if err != nil || d.skipUntilTable {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			f.Set(x)
+		}
+		d.errorContext.Field = nil
+		d.errorContext.Struct = nil
+	case reflect.Interface:
+		if v.Elem().IsValid() {
+			v = v.Elem()
+		} else {
+			v = makeMapStringInterface()
+		}
 
-	x, found, err = d.scopeTableTarget(false, x, string(n.Data))
-	if err != nil || !found {
-		return x, found, err
+		x, err := d.handleKeyPart(key, v, nextFn, makeFn)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			v = x
+		}
+		rv = v
+	default:
+		panic(fmt.Errorf("unhandled part: %s", v.Kind()))
 	}
 
-	v := x.get()
+	return rv, nil
+}
 
-	if v.Kind() == reflect.Ptr {
-		x = scopePtr(x)
-		v = x.get()
+// HandleArrayTablePart navigates the Go structure v using the key v. It is
+// only used for the prefix (non-last) parts of an array-table. When
+// encountering a collection, it should go to the last element.
+func (d *decoder) handleArrayTablePart(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	var makeFn valueMakerFn
+	if key.IsLast() {
+		makeFn = makeSliceInterface
+	} else {
+		makeFn = makeMapStringInterface
 	}
+	return d.handleKeyPart(key, v, d.handleArrayTableCollection, makeFn)
+}
 
-	if v.Kind() == reflect.Interface {
-		x = scopeInterface(true, x)
-		v = x.get()
+// HandleTable returns a reference when it has checked the next expression but
+// cannot handle it.
+func (d *decoder) handleTable(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	if v.Kind() == reflect.Slice {
+		if v.Len() == 0 {
+			return reflect.Value{}, newDecodeError(key.Node().Data, "cannot store a table in a slice")
+		}
+		elem := v.Index(v.Len() - 1)
+		x, err := d.handleTable(key, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			elem.Set(x)
+		}
+		return reflect.Value{}, nil
 	}
-
-	switch v.Kind() {
-	case reflect.Slice:
-		x = scopeSlice(true, x)
-	case reflect.Array:
-		x, err = d.scopeArray(true, x)
-	default:
+	if key.Next() {
+		// Still scoping the key
+		return d.handleTablePart(key, v)
 	}
-
-	return x, found, err
+	// Done scoping the key.
+	// Now handle all the key-value expressions in this table.
+	return d.handleKeyValues(v)
 }
 
-func (d *decoder) unmarshalKeyValue(x target, node ast.Node) error {
-	assertNode(ast.KeyValue, node)
+// Handle root expressions until the end of the document or the next
+// non-key-value.
+func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) {
+	var rv reflect.Value
+	for d.nextExpr() {
+		expr := d.expr()
+		if expr.Kind != ast.KeyValue {
+			// Stash the expression so that fromParser can just loop and use
+			// the right handler.
+			// We could just recurse ourselves here, but at least this gives a
+			// chance to pop the stack a bit.
+			d.stashExpr()
+			break
+		}
 
-	d.strict.EnterKeyValue(node)
-	defer d.strict.ExitKeyValue(node)
+		err := d.seen.CheckExpression(expr)
+		if err != nil {
+			return reflect.Value{}, err
+		}
 
-	x, found, err := d.scopeWithKey(x, node.Key())
-	if err != nil {
-		return err
+		x, err := d.handleKeyValue(expr, v)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			v = x
+			rv = x
+		}
 	}
+	return rv, nil
+}
 
-	// A struct in the path was not found. Skip this value.
-	if !found {
-		d.strict.MissingField(node)
-
-		return nil
-	}
+type (
+	handlerFn    func(key ast.Iterator, v reflect.Value) (reflect.Value, error)
+	valueMakerFn func() reflect.Value
+)
 
-	return d.unmarshalValue(x, node.Value())
+func makeMapStringInterface() reflect.Value {
+	return reflect.MakeMap(mapStringInterfaceType)
 }
 
-var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem()
-
-func tryTextUnmarshaler(x target, node ast.Node) (bool, error) {
-	v := x.get()
+func makeSliceInterface() reflect.Value {
+	return reflect.MakeSlice(sliceInterfaceType, 0, 16)
+}
 
-	if v.Kind() != reflect.Struct {
-		return false, nil
-	}
+func (d *decoder) handleTablePart(key ast.Iterator, v reflect.Value) (reflect.Value, error) {
+	return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface)
+}
 
+func (d *decoder) tryTextUnmarshaler(node *ast.Node, v reflect.Value) (bool, error) {
 	// Special case for time, because we allow to unmarshal to it from
 	// different kind of AST nodes.
 	if v.Type() == timeType {
 		return false, nil
 	}
 
-	if v.Type().Implements(textUnmarshalerType) {
-		err := v.Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
-		if err != nil {
-			return false, newDecodeError(node.Data, "error calling UnmarshalText: %w", err)
-		}
-
-		return true, nil
-	}
-
 	if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) {
 		err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data)
 		if err != nil {
-			return false, newDecodeError(node.Data, "error calling UnmarshalText: %w", err)
+			return false, newDecodeError(d.p.Raw(node.Raw), "%w", err)
 		}
 
 		return true, nil
@@ -367,65 +622,192 @@ func tryTextUnmarshaler(x target, node ast.Node) (bool, error) {
 	return false, nil
 }
 
-//nolint:cyclop
-func (d *decoder) unmarshalValue(x target, node ast.Node) error {
-	v := x.get()
-
-	if v.Kind() == reflect.Ptr {
-		if !v.Elem().IsValid() {
-			x.set(reflect.New(v.Type().Elem()))
-			v = x.get()
-		}
-
-		return d.unmarshalValue(valueTarget(v.Elem()), node)
+func (d *decoder) handleValue(value *ast.Node, v reflect.Value) error {
+	for v.Kind() == reflect.Ptr {
+		v = initAndDereferencePointer(v)
 	}
 
-	ok, err := tryTextUnmarshaler(x, node)
-	if ok {
+	ok, err := d.tryTextUnmarshaler(value, v)
+	if ok || err != nil {
 		return err
 	}
 
-	switch node.Kind {
+	switch value.Kind {
 	case ast.String:
-		return unmarshalString(x, node)
-	case ast.Bool:
-		return unmarshalBool(x, node)
+		return d.unmarshalString(value, v)
 	case ast.Integer:
-		return unmarshalInteger(x, node)
+		return d.unmarshalInteger(value, v)
 	case ast.Float:
-		return unmarshalFloat(x, node)
-	case ast.Array:
-		return d.unmarshalArray(x, node)
-	case ast.InlineTable:
-		return d.unmarshalInlineTable(x, node)
-	case ast.LocalDateTime:
-		return unmarshalLocalDateTime(x, node)
+		return d.unmarshalFloat(value, v)
+	case ast.Bool:
+		return d.unmarshalBool(value, v)
 	case ast.DateTime:
-		return unmarshalDateTime(x, node)
+		return d.unmarshalDateTime(value, v)
 	case ast.LocalDate:
-		return unmarshalLocalDate(x, node)
+		return d.unmarshalLocalDate(value, v)
+	case ast.LocalTime:
+		return d.unmarshalLocalTime(value, v)
+	case ast.LocalDateTime:
+		return d.unmarshalLocalDateTime(value, v)
+	case ast.InlineTable:
+		return d.unmarshalInlineTable(value, v)
+	case ast.Array:
+		return d.unmarshalArray(value, v)
 	default:
-		panic(fmt.Sprintf("unhandled node kind %s", node.Kind))
+		panic(fmt.Errorf("handleValue not implemented for %s", value.Kind))
 	}
 }
 
-func unmarshalLocalDate(x target, node ast.Node) error {
-	assertNode(ast.LocalDate, node)
+func (d *decoder) unmarshalArray(array *ast.Node, v reflect.Value) error {
+	switch v.Kind() {
+	case reflect.Slice:
+		if v.IsNil() {
+			v.Set(reflect.MakeSlice(v.Type(), 0, 16))
+		} else {
+			v.SetLen(0)
+		}
+	case reflect.Array:
+		// arrays are always initialized
+	case reflect.Interface:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			elem = reflect.New(sliceInterfaceType).Elem()
+			elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+		} else if elem.Kind() == reflect.Slice {
+			if elem.Type() != sliceInterfaceType {
+				elem = reflect.New(sliceInterfaceType).Elem()
+				elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16))
+			} else if !elem.CanSet() {
+				nelem := reflect.New(sliceInterfaceType).Elem()
+				nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap()))
+				reflect.Copy(nelem, elem)
+				elem = nelem
+			}
+		}
+		err := d.unmarshalArray(array, elem)
+		if err != nil {
+			return err
+		}
+		v.Set(elem)
+		return nil
+	default:
+		// TODO: use newDecodeError, but first the parser needs to fill
+		//   array.Data.
+		return d.typeMismatchError("array", v.Type())
+	}
 
-	v, err := parseLocalDate(node.Data)
+	elemType := v.Type().Elem()
+
+	it := array.Children()
+	idx := 0
+	for it.Next() {
+		n := it.Node()
+
+		// TODO: optimize
+		if v.Kind() == reflect.Slice {
+			elem := reflect.New(elemType).Elem()
+
+			err := d.handleValue(n, elem)
+			if err != nil {
+				return err
+			}
+
+			v.Set(reflect.Append(v, elem))
+		} else { // array
+			if idx >= v.Len() {
+				return nil
+			}
+			elem := v.Index(idx)
+			err := d.handleValue(n, elem)
+			if err != nil {
+				return err
+			}
+			idx++
+		}
+	}
+
+	return nil
+}
+
+func (d *decoder) unmarshalInlineTable(itable *ast.Node, v reflect.Value) error {
+	// Make sure v is an initialized object.
+	switch v.Kind() {
+	case reflect.Map:
+		if v.IsNil() {
+			v.Set(reflect.MakeMap(v.Type()))
+		}
+	case reflect.Struct:
+	// structs are always initialized.
+	case reflect.Interface:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			elem = makeMapStringInterface()
+			v.Set(elem)
+		}
+		return d.unmarshalInlineTable(itable, elem)
+	default:
+		return newDecodeError(itable.Data, "cannot store inline table in Go type %s", v.Kind())
+	}
+
+	it := itable.Children()
+	for it.Next() {
+		n := it.Node()
+
+		x, err := d.handleKeyValue(n, v)
+		if err != nil {
+			return err
+		}
+		if x.IsValid() {
+			v = x
+		}
+	}
+
+	return nil
+}
+
+func (d *decoder) unmarshalDateTime(value *ast.Node, v reflect.Value) error {
+	dt, err := parseDateTime(value.Data)
 	if err != nil {
 		return err
 	}
 
-	setDate(x, v)
+	v.Set(reflect.ValueOf(dt))
+	return nil
+}
+
+func (d *decoder) unmarshalLocalDate(value *ast.Node, v reflect.Value) error {
+	ld, err := parseLocalDate(value.Data)
+	if err != nil {
+		return err
+	}
+
+	if v.Type() == timeType {
+		cast := ld.AsTime(time.Local)
+		v.Set(reflect.ValueOf(cast))
+		return nil
+	}
+
+	v.Set(reflect.ValueOf(ld))
 
 	return nil
 }
 
-func unmarshalLocalDateTime(x target, node ast.Node) error {
-	assertNode(ast.LocalDateTime, node)
+func (d *decoder) unmarshalLocalTime(value *ast.Node, v reflect.Value) error {
+	lt, rest, err := parseLocalTime(value.Data)
+	if err != nil {
+		return err
+	}
+
+	if len(rest) > 0 {
+		return newDecodeError(rest, "extra characters at the end of a local time")
+	}
 
-	v, rest, err := parseLocalDateTime(node.Data)
+	v.Set(reflect.ValueOf(lt))
+	return nil
+}
+
+func (d *decoder) unmarshalLocalDateTime(value *ast.Node, v reflect.Value) error {
+	ldt, rest, err := parseLocalDateTime(value.Data)
 	if err != nil {
 		return err
 	}
@@ -434,160 +816,412 @@ func unmarshalLocalDateTime(x target, node ast.Node) error {
 		return newDecodeError(rest, "extra characters at the end of a local date time")
 	}
 
-	setLocalDateTime(x, v)
+	if v.Type() == timeType {
+		cast := ldt.AsTime(time.Local)
+
+		v.Set(reflect.ValueOf(cast))
+		return nil
+	}
+
+	v.Set(reflect.ValueOf(ldt))
 
 	return nil
 }
 
-func unmarshalDateTime(x target, node ast.Node) error {
-	assertNode(ast.DateTime, node)
+func (d *decoder) unmarshalBool(value *ast.Node, v reflect.Value) error {
+	b := value.Data[0] == 't'
+
+	switch v.Kind() {
+	case reflect.Bool:
+		v.SetBool(b)
+	case reflect.Interface:
+		v.Set(reflect.ValueOf(b))
+	default:
+		return newDecodeError(value.Data, "cannot assign boolean to a %t", b)
+	}
+
+	return nil
+}
 
-	v, err := parseDateTime(node.Data)
+func (d *decoder) unmarshalFloat(value *ast.Node, v reflect.Value) error {
+	f, err := parseFloat(value.Data)
 	if err != nil {
 		return err
 	}
 
-	setDateTime(x, v)
+	switch v.Kind() {
+	case reflect.Float64:
+		v.SetFloat(f)
+	case reflect.Float32:
+		if f > math.MaxFloat32 {
+			return newDecodeError(value.Data, "number %f does not fit in a float32", f)
+		}
+		v.SetFloat(f)
+	case reflect.Interface:
+		v.Set(reflect.ValueOf(f))
+	default:
+		return newDecodeError(value.Data, "float cannot be assigned to %s", v.Kind())
+	}
 
 	return nil
 }
 
-func setLocalDateTime(x target, v LocalDateTime) {
-	if x.get().Type() == timeType {
-		cast := v.In(time.Local)
+const (
+	maxInt = int64(^uint(0) >> 1)
+	minInt = -maxInt - 1
+)
 
-		setDateTime(x, cast)
-		return
+// Maximum value of uint for decoding. Currently the decoder parses the integer
+// into an int64. As a result, on architectures where uint is 64 bits, the
+// effective maximum uint we can decode is the maximum of int64. On
+// architectures where uint is 32 bits, the maximum value we can decode is
+// lower: the maximum of uint32. I didn't find a way to figure out this value at
+// compile time, so it is computed during initialization.
+var maxUint int64 = math.MaxInt64
+
+func init() {
+	m := uint64(^uint(0))
+	if m < uint64(maxUint) {
+		maxUint = int64(m)
 	}
-
-	x.set(reflect.ValueOf(v))
 }
 
-func setDateTime(x target, v time.Time) {
-	x.set(reflect.ValueOf(v))
-}
+func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
+	i, err := parseInteger(value.Data)
+	if err != nil {
+		return err
+	}
 
-var timeType = reflect.TypeOf(time.Time{})
+	var r reflect.Value
 
-func setDate(x target, v LocalDate) {
-	if x.get().Type() == timeType {
-		cast := v.In(time.Local)
+	switch v.Kind() {
+	case reflect.Int64:
+		v.SetInt(i)
+		return nil
+	case reflect.Int32:
+		if i < math.MinInt32 || i > math.MaxInt32 {
+			return fmt.Errorf("toml: number %d does not fit in an int32", i)
+		}
+
+		r = reflect.ValueOf(int32(i))
+	case reflect.Int16:
+		if i < math.MinInt16 || i > math.MaxInt16 {
+			return fmt.Errorf("toml: number %d does not fit in an int16", i)
+		}
+
+		r = reflect.ValueOf(int16(i))
+	case reflect.Int8:
+		if i < math.MinInt8 || i > math.MaxInt8 {
+			return fmt.Errorf("toml: number %d does not fit in an int8", i)
+		}
 
-		setDateTime(x, cast)
-		return
+		r = reflect.ValueOf(int8(i))
+	case reflect.Int:
+		if i < minInt || i > maxInt {
+			return fmt.Errorf("toml: number %d does not fit in an int", i)
+		}
+
+		r = reflect.ValueOf(int(i))
+	case reflect.Uint64:
+		if i < 0 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint64", i)
+		}
+
+		r = reflect.ValueOf(uint64(i))
+	case reflect.Uint32:
+		if i < 0 || i > math.MaxUint32 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint32", i)
+		}
+
+		r = reflect.ValueOf(uint32(i))
+	case reflect.Uint16:
+		if i < 0 || i > math.MaxUint16 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint16", i)
+		}
+
+		r = reflect.ValueOf(uint16(i))
+	case reflect.Uint8:
+		if i < 0 || i > math.MaxUint8 {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint8", i)
+		}
+
+		r = reflect.ValueOf(uint8(i))
+	case reflect.Uint:
+		if i < 0 || i > maxUint {
+			return fmt.Errorf("toml: negative number %d does not fit in an uint", i)
+		}
+
+		r = reflect.ValueOf(uint(i))
+	case reflect.Interface:
+		r = reflect.ValueOf(i)
+	default:
+		return d.typeMismatchError("integer", v.Type())
 	}
 
-	x.set(reflect.ValueOf(v))
-}
+	if !r.Type().AssignableTo(v.Type()) {
+		r = r.Convert(v.Type())
+	}
 
-func unmarshalString(x target, node ast.Node) error {
-	assertNode(ast.String, node)
+	v.Set(r)
 
-	return setString(x, string(node.Data))
+	return nil
 }
 
-func unmarshalBool(x target, node ast.Node) error {
-	assertNode(ast.Bool, node)
-	v := node.Data[0] == 't'
+func (d *decoder) unmarshalString(value *ast.Node, v reflect.Value) error {
+	switch v.Kind() {
+	case reflect.String:
+		v.SetString(string(value.Data))
+	case reflect.Interface:
+		v.Set(reflect.ValueOf(string(value.Data)))
+	default:
+		return newDecodeError(d.p.Raw(value.Raw), "cannot store TOML string into a Go %s", v.Kind())
+	}
 
-	return setBool(x, v)
+	return nil
 }
 
-func unmarshalInteger(x target, node ast.Node) error {
-	assertNode(ast.Integer, node)
+func (d *decoder) handleKeyValue(expr *ast.Node, v reflect.Value) (reflect.Value, error) {
+	d.strict.EnterKeyValue(expr)
 
-	v, err := parseInteger(node.Data)
-	if err != nil {
-		return err
+	v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v)
+	if d.skipUntilTable {
+		d.strict.MissingField(expr)
+		d.skipUntilTable = false
 	}
 
-	return setInt64(x, v)
-}
+	d.strict.ExitKeyValue(expr)
 
-func unmarshalFloat(x target, node ast.Node) error {
-	assertNode(ast.Float, node)
+	return v, err
+}
 
-	v, err := parseFloat(node.Data)
-	if err != nil {
-		return err
+func (d *decoder) handleKeyValueInner(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
+	if key.Next() {
+		// Still scoping the key
+		return d.handleKeyValuePart(key, value, v)
 	}
-
-	return setFloat64(x, v)
+	// Done scoping the key.
+	// v is whatever Go value we need to fill.
+	return reflect.Value{}, d.handleValue(value, v)
 }
 
-func (d *decoder) unmarshalInlineTable(x target, node ast.Node) error {
-	assertNode(ast.InlineTable, node)
+func (d *decoder) handleKeyValuePart(key ast.Iterator, value *ast.Node, v reflect.Value) (reflect.Value, error) {
+	// contains the replacement for v
+	var rv reflect.Value
 
-	ensureMapIfInterface(x)
+	// First, dispatch over v to make sure it is a valid object.
+	// There is no guarantee over what it could be.
+	switch v.Kind() {
+	case reflect.Map:
+		vt := v.Type()
 
-	it := node.Children()
-	for it.Next() {
-		n := it.Node()
+		mk := reflect.ValueOf(string(key.Node().Data))
+		mkt := stringType
+
+		keyType := vt.Key()
+		if !mkt.AssignableTo(keyType) {
+			if !mkt.ConvertibleTo(keyType) {
+				return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", mkt, keyType)
+			}
 
-		err := d.unmarshalKeyValue(x, n)
+			mk = mk.Convert(keyType)
+		}
+
+		// If the map does not exist, create it.
+		if v.IsNil() {
+			v = reflect.MakeMap(vt)
+			rv = v
+		}
+
+		mv := v.MapIndex(mk)
+		set := false
+		if !mv.IsValid() {
+			set = true
+			mv = reflect.New(v.Type().Elem()).Elem()
+		} else {
+			if key.IsLast() {
+				var x interface{}
+				mv = reflect.ValueOf(&x).Elem()
+				set = true
+			}
+		}
+
+		nv, err := d.handleKeyValueInner(key, value, mv)
 		if err != nil {
-			return err
+			return reflect.Value{}, err
+		}
+		if nv.IsValid() {
+			mv = nv
+			set = true
+		}
+
+		if set {
+			v.SetMapIndex(mk, mv)
+		}
+	case reflect.Struct:
+		path, found := structFieldPath(v, string(key.Node().Data))
+		if !found {
+			d.skipUntilTable = true
+			break
+		}
+
+		if d.errorContext == nil {
+			d.errorContext = new(errorContext)
+		}
+		t := v.Type()
+		d.errorContext.Struct = t
+		d.errorContext.Field = path
+
+		f := fieldByIndex(v, path)
+		x, err := d.handleKeyValueInner(key, value, f)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+
+		if x.IsValid() {
+			f.Set(x)
+		}
+		d.errorContext.Struct = nil
+		d.errorContext.Field = nil
+	case reflect.Interface:
+		v = v.Elem()
+
+		// Following encoding/json: decoding an object into an
+		// interface{}, it needs to always hold a
+		// map[string]interface{}. This is for the types to be
+		// consistent whether a previous value was set or not.
+		if !v.IsValid() || v.Type() != mapStringInterfaceType {
+			v = makeMapStringInterface()
+		}
+
+		x, err := d.handleKeyValuePart(key, value, v)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if x.IsValid() {
+			v = x
 		}
+		rv = v
+	case reflect.Ptr:
+		elem := v.Elem()
+		if !elem.IsValid() {
+			ptr := reflect.New(v.Type().Elem())
+			v.Set(ptr)
+			rv = v
+			elem = ptr.Elem()
+		}
+
+		elem2, err := d.handleKeyValuePart(key, value, elem)
+		if err != nil {
+			return reflect.Value{}, err
+		}
+		if elem2.IsValid() {
+			elem = elem2
+		}
+		v.Elem().Set(elem)
+	default:
+		return reflect.Value{}, fmt.Errorf("unhandled kv part: %s", v.Kind())
 	}
 
-	return nil
+	return rv, nil
 }
 
-func (d *decoder) unmarshalArray(x target, node ast.Node) error {
-	assertNode(ast.Array, node)
+func initAndDereferencePointer(v reflect.Value) reflect.Value {
+	var elem reflect.Value
+	if v.IsNil() {
+		ptr := reflect.New(v.Type().Elem())
+		v.Set(ptr)
+	}
+	elem = v.Elem()
+	return elem
+}
 
-	err := ensureValueIndexable(x)
-	if err != nil {
-		return err
+// Same as reflect.Value.FieldByIndex, but creates pointers if needed.
+func fieldByIndex(v reflect.Value, path []int) reflect.Value {
+	for i, x := range path {
+		v = v.Field(x)
+
+		if i < len(path)-1 && v.Kind() == reflect.Ptr {
+			if v.IsNil() {
+				v.Set(reflect.New(v.Type().Elem()))
+			}
+			v = v.Elem()
+		}
 	}
+	return v
+}
+
+type fieldPathsMap = map[string][]int
+
+var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap
 
-	// Special work around when unmarshaling into an array.
-	// If the array is not addressable, for example when stored as a value in a
-	// map, calling elementAt in the inner function would fail.
-	// Instead, we allocate a new array that will be filled then inserted into
-	// the container.
-	// This problem does not exist with slices because they are addressable.
-	// There may be a better way of doing this, but it is not obvious to me
-	// with the target system.
-	if x.get().Kind() == reflect.Array {
-		container := x
-		newArrayPtr := reflect.New(x.get().Type())
-		x = valueTarget(newArrayPtr.Elem())
-		defer func() {
-			container.set(newArrayPtr.Elem())
-		}()
+func structFieldPath(v reflect.Value, name string) ([]int, bool) {
+	t := v.Type()
+
+	cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap)
+	fieldPaths, ok := cache[danger.MakeTypeID(t)]
+
+	if !ok {
+		fieldPaths = map[string][]int{}
+
+		forEachField(t, nil, func(name string, path []int) {
+			fieldPaths[name] = path
+			// extra copy for the case-insensitive match
+			fieldPaths[strings.ToLower(name)] = path
+		})
+
+		newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1)
+		newCache[danger.MakeTypeID(t)] = fieldPaths
+		for k, v := range cache {
+			newCache[k] = v
+		}
+		globalFieldPathsCache.Store(newCache)
 	}
 
-	return d.unmarshalArrayInner(x, node)
+	path, ok := fieldPaths[name]
+	if !ok {
+		path, ok = fieldPaths[strings.ToLower(name)]
+	}
+	return path, ok
 }
 
-func (d *decoder) unmarshalArrayInner(x target, node ast.Node) error {
-	idx := 0
+func forEachField(t reflect.Type, path []int, do func(name string, path []int)) {
+	n := t.NumField()
+	for i := 0; i < n; i++ {
+		f := t.Field(i)
 
-	it := node.Children()
-	for it.Next() {
-		n := it.Node()
+		if !f.Anonymous && f.PkgPath != "" {
+			// only consider exported fields.
+			continue
+		}
 
-		v := elementAt(x, idx)
+		fieldPath := append(path, i)
+		fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]
 
-		if v == nil {
-			// when we go out of bound for an array just stop processing it to
-			// mimic encoding/json
-			break
+		name := f.Tag.Get("toml")
+		if name == "-" {
+			continue
 		}
 
-		err := d.unmarshalValue(v, n)
-		if err != nil {
-			return err
+		if i := strings.IndexByte(name, ','); i >= 0 {
+			name = name[:i]
 		}
 
-		idx++
-	}
-	return nil
-}
+		if f.Anonymous && name == "" {
+			t2 := f.Type
+			if t2.Kind() == reflect.Ptr {
+				t2 = t2.Elem()
+			}
+
+			if t2.Kind() == reflect.Struct {
+				forEachField(t2, fieldPath, do)
+			}
+			continue
+		}
+
+		if name == "" {
+			name = f.Name
+		}
 
-func assertNode(expected ast.Kind, node ast.Node) {
-	if node.Kind != expected {
-		panic(fmt.Sprintf("expected node of kind %s, not %s", expected, node.Kind))
+		do(name, fieldPath)
 	}
 }
diff --git a/vendor/github.com/pelletier/go-toml/v2/utf8.go b/vendor/github.com/pelletier/go-toml/v2/utf8.go
new file mode 100644
index 000000000..d47a4f20c
--- /dev/null
+++ b/vendor/github.com/pelletier/go-toml/v2/utf8.go
@@ -0,0 +1,240 @@
+package toml
+
+import (
+	"unicode/utf8"
+)
+
+type utf8Err struct {
+	Index int
+	Size  int
+}
+
+func (u utf8Err) Zero() bool {
+	return u.Size == 0
+}
+
+// Verified that a given string is only made of valid UTF-8 characters allowed
+// by the TOML spec:
+//
+// Any Unicode character may be used except those that must be escaped:
+// quotation mark, backslash, and the control characters other than tab (U+0000
+// to U+0008, U+000A to U+001F, U+007F).
+//
+// It is a copy of the Go 1.17 utf8.Valid implementation, tweaked to exit early
+// when a character is not allowed.
+//
+// The returned utf8Err is Zero() if the string is valid, or contains the byte
+// index and size of the invalid character.
+//
+// quotation mark => already checked
+// backslash => already checked
+// 0-0x8 => invalid
+// 0x9 => tab, ok
+// 0xA - 0x1F => invalid
+// 0x7F => invalid
+func utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) {
+	// Fast path. Check for and skip 8 bytes of ASCII characters per iteration.
+	offset := 0
+	for len(p) >= 8 {
+		// Combining two 32 bit loads allows the same code to be used
+		// for 32 and 64 bit platforms.
+		// The compiler can generate a 32bit load for first32 and second32
+		// on many platforms. See test/codegen/memcombine.go.
+		first32 := uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24
+		second32 := uint32(p[4]) | uint32(p[5])<<8 | uint32(p[6])<<16 | uint32(p[7])<<24
+		if (first32|second32)&0x80808080 != 0 {
+			// Found a non ASCII byte (>= RuneSelf).
+			break
+		}
+
+		for i, b := range p[:8] {
+			if invalidAscii(b) {
+				err.Index = offset + i
+				err.Size = 1
+				return
+			}
+		}
+
+		p = p[8:]
+		offset += 8
+	}
+	n := len(p)
+	for i := 0; i < n; {
+		pi := p[i]
+		if pi < utf8.RuneSelf {
+			if invalidAscii(pi) {
+				err.Index = offset + i
+				err.Size = 1
+				return
+			}
+			i++
+			continue
+		}
+		x := first[pi]
+		if x == xx {
+			// Illegal starter byte.
+			err.Index = offset + i
+			err.Size = 1
+			return
+		}
+		size := int(x & 7)
+		if i+size > n {
+			// Short or invalid.
+			err.Index = offset + i
+			err.Size = n - i
+			return
+		}
+		accept := acceptRanges[x>>4]
+		if c := p[i+1]; c < accept.lo || accept.hi < c {
+			err.Index = offset + i
+			err.Size = 2
+			return
+		} else if size == 2 {
+		} else if c := p[i+2]; c < locb || hicb < c {
+			err.Index = offset + i
+			err.Size = 3
+			return
+		} else if size == 3 {
+		} else if c := p[i+3]; c < locb || hicb < c {
+			err.Index = offset + i
+			err.Size = 4
+			return
+		}
+		i += size
+	}
+	return
+}
+
+// Return the size of the next rune if valid, 0 otherwise.
+func utf8ValidNext(p []byte) int {
+	c := p[0]
+
+	if c < utf8.RuneSelf {
+		if invalidAscii(c) {
+			return 0
+		}
+		return 1
+	}
+
+	x := first[c]
+	if x == xx {
+		// Illegal starter byte.
+		return 0
+	}
+	size := int(x & 7)
+	if size > len(p) {
+		// Short or invalid.
+		return 0
+	}
+	accept := acceptRanges[x>>4]
+	if c := p[1]; c < accept.lo || accept.hi < c {
+		return 0
+	} else if size == 2 {
+	} else if c := p[2]; c < locb || hicb < c {
+		return 0
+	} else if size == 3 {
+	} else if c := p[3]; c < locb || hicb < c {
+		return 0
+	}
+
+	return size
+}
+
+var invalidAsciiTable = [256]bool{
+	0x00: true,
+	0x01: true,
+	0x02: true,
+	0x03: true,
+	0x04: true,
+	0x05: true,
+	0x06: true,
+	0x07: true,
+	0x08: true,
+	// 0x09 TAB
+	// 0x0A LF
+	0x0B: true,
+	0x0C: true,
+	// 0x0D CR
+	0x0E: true,
+	0x0F: true,
+	0x10: true,
+	0x11: true,
+	0x12: true,
+	0x13: true,
+	0x14: true,
+	0x15: true,
+	0x16: true,
+	0x17: true,
+	0x18: true,
+	0x19: true,
+	0x1A: true,
+	0x1B: true,
+	0x1C: true,
+	0x1D: true,
+	0x1E: true,
+	0x1F: true,
+	// 0x20 - 0x7E Printable ASCII characters
+	0x7F: true,
+}
+
+func invalidAscii(b byte) bool {
+	return invalidAsciiTable[b]
+}
+
+// acceptRange gives the range of valid values for the second byte in a UTF-8
+// sequence.
+type acceptRange struct {
+	lo uint8 // lowest value for second byte.
+	hi uint8 // highest value for second byte.
+}
+
+// acceptRanges has size 16 to avoid bounds checks in the code that uses it.
+var acceptRanges = [16]acceptRange{
+	0: {locb, hicb},
+	1: {0xA0, hicb},
+	2: {locb, 0x9F},
+	3: {0x90, hicb},
+	4: {locb, 0x8F},
+}
+
+// first is information about the first byte in a UTF-8 sequence.
+var first = [256]uint8{
+	//   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F
+	as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F
+	//   1   2   3   4   5   6   7   8   9   A   B   C   D   E   F
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF
+	xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF
+	xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF
+	s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF
+	s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF
+	s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF
+}
+
+const (
+	// The default lowest and highest continuation byte.
+	locb = 0b10000000
+	hicb = 0b10111111
+
+	// These names of these constants are chosen to give nice alignment in the
+	// table below. The first nibble is an index into acceptRanges or F for
+	// special one-byte cases. The second nibble is the Rune length or the
+	// Status for the special one-byte case.
+	xx = 0xF1 // invalid: size 1
+	as = 0xF0 // ASCII: size 1
+	s1 = 0x02 // accept 0, size 2
+	s2 = 0x13 // accept 1, size 3
+	s3 = 0x03 // accept 0, size 3
+	s4 = 0x23 // accept 2, size 3
+	s5 = 0x34 // accept 3, size 4
+	s6 = 0x04 // accept 0, size 4
+	s7 = 0x44 // accept 4, size 4
+)
diff --git a/vendor/modules.txt b/vendor/modules.txt
index fb91a46f7..1cfbec0bb 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -447,12 +447,12 @@ github.com/openzipkin/zipkin-go/model
 github.com/openzipkin/zipkin-go/propagation
 github.com/openzipkin/zipkin-go/reporter
 github.com/openzipkin/zipkin-go/reporter/http
-# github.com/pelletier/go-toml/v2 v2.0.0-beta.2
-## explicit; go 1.15
+# github.com/pelletier/go-toml/v2 v2.0.5
+## explicit; go 1.16
 github.com/pelletier/go-toml/v2
 github.com/pelletier/go-toml/v2/internal/ast
+github.com/pelletier/go-toml/v2/internal/danger
 github.com/pelletier/go-toml/v2/internal/tracker
-github.com/pelletier/go-toml/v2/internal/unsafe
 # github.com/pierrec/lz4 v2.6.1+incompatible
 ## explicit
 github.com/pierrec/lz4
@@ -1384,7 +1384,7 @@ knative.dev/control-protocol/pkg/message
 knative.dev/control-protocol/pkg/network
 knative.dev/control-protocol/pkg/reconciler
 knative.dev/control-protocol/pkg/service
-# knative.dev/eventing v0.34.1-0.20221013172353-24adf198c60c
+# knative.dev/eventing v0.34.1-0.20221018032010-0fe923cd8a5b
 ## explicit; go 1.18
 knative.dev/eventing/pkg/adapter/v2
 knative.dev/eventing/pkg/adapter/v2/test


Test patch:
diff --git a/vendor/knative.dev/eventing/test/upgrade/prober/wathola/config/reader.go b/vendor/knative.dev/eventing/test/upgrade/prober/wathola/config/reader.go
index f2c725ab5..b77450d0b 100644
--- a/vendor/knative.dev/eventing/test/upgrade/prober/wathola/config/reader.go
+++ b/vendor/knative.dev/eventing/test/upgrade/prober/wathola/config/reader.go
@@ -52,7 +52,7 @@ func Read(configFile string) error {
 		return err
 	}
 	d := toml.NewDecoder(r)
-	d.SetStrict(true)
+	d.DisallowUnknownFields()
 	err = d.Decode(Instance)
 	return err
 }