Update go-toml to v2
Updates host file parsing to use new v2 method rather than the removed toml.Tree. Signed-off-by: Derek McGowan <derek@mcg.dev>
This commit is contained in:
		
							
								
								
									
										132
									
								
								vendor/github.com/pelletier/go-toml/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										132
									
								
								vendor/github.com/pelletier/go-toml/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,132 +0,0 @@
 | 
			
		||||
## Contributing
 | 
			
		||||
 | 
			
		||||
Thank you for your interest in go-toml! We appreciate you considering
 | 
			
		||||
contributing to go-toml!
 | 
			
		||||
 | 
			
		||||
The main goal is the project is to provide an easy-to-use TOML
 | 
			
		||||
implementation for Go that gets the job done and gets out of your way –
 | 
			
		||||
dealing with TOML is probably not the central piece of your project.
 | 
			
		||||
 | 
			
		||||
As the single maintainer of go-toml, time is scarce. All help, big or
 | 
			
		||||
small, is more than welcomed!
 | 
			
		||||
 | 
			
		||||
### Ask questions
 | 
			
		||||
 | 
			
		||||
Any question you may have, somebody else might have it too. Always feel
 | 
			
		||||
free to ask them on the [issues tracker][issues-tracker].  We will try to
 | 
			
		||||
answer them as clearly and quickly as possible, time permitting.
 | 
			
		||||
 | 
			
		||||
Asking questions also helps us identify areas where the documentation needs
 | 
			
		||||
improvement, or new features that weren't envisioned before. Sometimes, a
 | 
			
		||||
seemingly innocent question leads to the fix of a bug. Don't hesitate and
 | 
			
		||||
ask away!
 | 
			
		||||
 | 
			
		||||
### Improve the documentation
 | 
			
		||||
 | 
			
		||||
The best way to share your knowledge and experience with go-toml is to
 | 
			
		||||
improve the documentation. Fix a typo, clarify an interface, add an
 | 
			
		||||
example, anything goes!
 | 
			
		||||
 | 
			
		||||
The documentation is present in the [README][readme] and thorough the
 | 
			
		||||
source code. On release, it gets updated on [pkg.go.dev][pkg.go.dev]. To make a
 | 
			
		||||
change to the documentation, create a pull request with your proposed
 | 
			
		||||
changes. For simple changes like that, the easiest way to go is probably
 | 
			
		||||
the "Fork this project and edit the file" button on Github, displayed at
 | 
			
		||||
the top right of the file. Unless it's a trivial change (for example a
 | 
			
		||||
typo), provide a little bit of context in your pull request description or
 | 
			
		||||
commit message.
 | 
			
		||||
 | 
			
		||||
### Report a bug
 | 
			
		||||
 | 
			
		||||
Found a bug! Sorry to hear that :(. Help us and other track them down and
 | 
			
		||||
fix by reporting it. [File a new bug report][bug-report] on the [issues
 | 
			
		||||
tracker][issues-tracker]. The template should provide enough guidance on
 | 
			
		||||
what to include. When in doubt: add more details! By reducing ambiguity and
 | 
			
		||||
providing more information, it decreases back and forth and saves everyone
 | 
			
		||||
time.
 | 
			
		||||
 | 
			
		||||
### Code changes
 | 
			
		||||
 | 
			
		||||
Want to contribute a patch? Very happy to hear that!
 | 
			
		||||
 | 
			
		||||
First, some high-level rules:
 | 
			
		||||
 | 
			
		||||
* A short proposal with some POC code is better than a lengthy piece of
 | 
			
		||||
  text with no code. Code speaks louder than words.
 | 
			
		||||
* No backward-incompatible patch will be accepted unless discussed.
 | 
			
		||||
  Sometimes it's hard, and Go's lack of versioning by default does not
 | 
			
		||||
  help, but we try not to break people's programs unless we absolutely have
 | 
			
		||||
  to.
 | 
			
		||||
* If you are writing a new feature or extending an existing one, make sure
 | 
			
		||||
  to write some documentation.
 | 
			
		||||
* Bug fixes need to be accompanied with regression tests.
 | 
			
		||||
* New code needs to be tested.
 | 
			
		||||
* Your commit messages need to explain why the change is needed, even if
 | 
			
		||||
  already included in the PR description.
 | 
			
		||||
 | 
			
		||||
It does sound like a lot, but those best practices are here to save time
 | 
			
		||||
overall and continuously improve the quality of the project, which is
 | 
			
		||||
something everyone benefits from.
 | 
			
		||||
 | 
			
		||||
#### Get started
 | 
			
		||||
 | 
			
		||||
The fairly standard code contribution process looks like that:
 | 
			
		||||
 | 
			
		||||
1. [Fork the project][fork].
 | 
			
		||||
2. Make your changes, commit on any branch you like.
 | 
			
		||||
3. [Open up a pull request][pull-request]
 | 
			
		||||
4. Review, potential ask for changes.
 | 
			
		||||
5. Merge. You're in!
 | 
			
		||||
 | 
			
		||||
Feel free to ask for help! You can create draft pull requests to gather
 | 
			
		||||
some early feedback!
 | 
			
		||||
 | 
			
		||||
#### Run the tests
 | 
			
		||||
 | 
			
		||||
You can run tests for go-toml using Go's test tool: `go test ./...`.
 | 
			
		||||
When creating a pull requests, all tests will be ran on Linux on a few Go
 | 
			
		||||
versions (Travis CI), and on Windows using the latest Go version
 | 
			
		||||
(AppVeyor).
 | 
			
		||||
 | 
			
		||||
#### Style
 | 
			
		||||
 | 
			
		||||
Try to look around and follow the same format and structure as the rest of
 | 
			
		||||
the code. We enforce using `go fmt` on the whole code base.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
### Maintainers-only
 | 
			
		||||
 | 
			
		||||
#### Merge pull request
 | 
			
		||||
 | 
			
		||||
Checklist:
 | 
			
		||||
 | 
			
		||||
* Passing CI.
 | 
			
		||||
* Does not introduce backward-incompatible changes (unless discussed).
 | 
			
		||||
* Has relevant doc changes.
 | 
			
		||||
* Has relevant unit tests.
 | 
			
		||||
 | 
			
		||||
1. Merge using "squash and merge".
 | 
			
		||||
2. Make sure to edit the commit message to keep all the useful information
 | 
			
		||||
   nice and clean.
 | 
			
		||||
3. Make sure the commit title is clear and contains the PR number (#123).
 | 
			
		||||
 | 
			
		||||
#### 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].
 | 
			
		||||
 | 
			
		||||
[issues-tracker]: https://github.com/pelletier/go-toml/issues
 | 
			
		||||
[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md
 | 
			
		||||
[pkg.go.dev]: https://pkg.go.dev/github.com/pelletier/go-toml
 | 
			
		||||
[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
 | 
			
		||||
							
								
								
									
										11
									
								
								vendor/github.com/pelletier/go-toml/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										11
									
								
								vendor/github.com/pelletier/go-toml/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,11 +0,0 @@
 | 
			
		||||
FROM golang:1.12-alpine3.9 as builder
 | 
			
		||||
WORKDIR /go/src/github.com/pelletier/go-toml
 | 
			
		||||
COPY . .
 | 
			
		||||
ENV CGO_ENABLED=0
 | 
			
		||||
ENV GOOS=linux
 | 
			
		||||
RUN go install ./...
 | 
			
		||||
 | 
			
		||||
FROM scratch
 | 
			
		||||
COPY --from=builder /go/bin/tomll /usr/bin/tomll
 | 
			
		||||
COPY --from=builder /go/bin/tomljson /usr/bin/tomljson
 | 
			
		||||
COPY --from=builder /go/bin/jsontoml /usr/bin/jsontoml
 | 
			
		||||
							
								
								
									
										247
									
								
								vendor/github.com/pelletier/go-toml/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										247
									
								
								vendor/github.com/pelletier/go-toml/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,247 +0,0 @@
 | 
			
		||||
The bulk of github.com/pelletier/go-toml is distributed under the MIT license
 | 
			
		||||
(see below), with the exception of localtime.go and localtime.test.go.
 | 
			
		||||
Those two files have been copied over from Google's civil library at revision
 | 
			
		||||
ed46f5086358513cf8c25f8e3f022cb838a49d66, and are distributed under the Apache
 | 
			
		||||
2.0 license (see below).
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
github.com/pelletier/go-toml:
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
Copyright (c) 2013 - 2021 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
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
localtime.go, localtime_test.go:
 | 
			
		||||
 | 
			
		||||
Originals:
 | 
			
		||||
    https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/civil/civil.go
 | 
			
		||||
    https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/civil/civil_test.go
 | 
			
		||||
Changes:
 | 
			
		||||
    * Renamed files from civil* to localtime*.
 | 
			
		||||
    * Package changed from civil to toml.
 | 
			
		||||
    * 'Local' prefix added to all structs.
 | 
			
		||||
License:
 | 
			
		||||
    https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/LICENSE
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                                 Apache License
 | 
			
		||||
                           Version 2.0, January 2004
 | 
			
		||||
                        http://www.apache.org/licenses/
 | 
			
		||||
 | 
			
		||||
   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
 | 
			
		||||
 | 
			
		||||
   1. Definitions.
 | 
			
		||||
 | 
			
		||||
      "License" shall mean the terms and conditions for use, reproduction,
 | 
			
		||||
      and distribution as defined by Sections 1 through 9 of this document.
 | 
			
		||||
 | 
			
		||||
      "Licensor" shall mean the copyright owner or entity authorized by
 | 
			
		||||
      the copyright owner that is granting the License.
 | 
			
		||||
 | 
			
		||||
      "Legal Entity" shall mean the union of the acting entity and all
 | 
			
		||||
      other entities that control, are controlled by, or are under common
 | 
			
		||||
      control with that entity. For the purposes of this definition,
 | 
			
		||||
      "control" means (i) the power, direct or indirect, to cause the
 | 
			
		||||
      direction or management of such entity, whether by contract or
 | 
			
		||||
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
 | 
			
		||||
      outstanding shares, or (iii) beneficial ownership of such entity.
 | 
			
		||||
 | 
			
		||||
      "You" (or "Your") shall mean an individual or Legal Entity
 | 
			
		||||
      exercising permissions granted by this License.
 | 
			
		||||
 | 
			
		||||
      "Source" form shall mean the preferred form for making modifications,
 | 
			
		||||
      including but not limited to software source code, documentation
 | 
			
		||||
      source, and configuration files.
 | 
			
		||||
 | 
			
		||||
      "Object" form shall mean any form resulting from mechanical
 | 
			
		||||
      transformation or translation of a Source form, including but
 | 
			
		||||
      not limited to compiled object code, generated documentation,
 | 
			
		||||
      and conversions to other media types.
 | 
			
		||||
 | 
			
		||||
      "Work" shall mean the work of authorship, whether in Source or
 | 
			
		||||
      Object form, made available under the License, as indicated by a
 | 
			
		||||
      copyright notice that is included in or attached to the work
 | 
			
		||||
      (an example is provided in the Appendix below).
 | 
			
		||||
 | 
			
		||||
      "Derivative Works" shall mean any work, whether in Source or Object
 | 
			
		||||
      form, that is based on (or derived from) the Work and for which the
 | 
			
		||||
      editorial revisions, annotations, elaborations, or other modifications
 | 
			
		||||
      represent, as a whole, an original work of authorship. For the purposes
 | 
			
		||||
      of this License, Derivative Works shall not include works that remain
 | 
			
		||||
      separable from, or merely link (or bind by name) to the interfaces of,
 | 
			
		||||
      the Work and Derivative Works thereof.
 | 
			
		||||
 | 
			
		||||
      "Contribution" shall mean any work of authorship, including
 | 
			
		||||
      the original version of the Work and any modifications or additions
 | 
			
		||||
      to that Work or Derivative Works thereof, that is intentionally
 | 
			
		||||
      submitted to Licensor for inclusion in the Work by the copyright owner
 | 
			
		||||
      or by an individual or Legal Entity authorized to submit on behalf of
 | 
			
		||||
      the copyright owner. For the purposes of this definition, "submitted"
 | 
			
		||||
      means any form of electronic, verbal, or written communication sent
 | 
			
		||||
      to the Licensor or its representatives, including but not limited to
 | 
			
		||||
      communication on electronic mailing lists, source code control systems,
 | 
			
		||||
      and issue tracking systems that are managed by, or on behalf of, the
 | 
			
		||||
      Licensor for the purpose of discussing and improving the Work, but
 | 
			
		||||
      excluding communication that is conspicuously marked or otherwise
 | 
			
		||||
      designated in writing by the copyright owner as "Not a Contribution."
 | 
			
		||||
 | 
			
		||||
      "Contributor" shall mean Licensor and any individual or Legal Entity
 | 
			
		||||
      on behalf of whom a Contribution has been received by Licensor and
 | 
			
		||||
      subsequently incorporated within the Work.
 | 
			
		||||
 | 
			
		||||
   2. Grant of Copyright License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      copyright license to reproduce, prepare Derivative Works of,
 | 
			
		||||
      publicly display, publicly perform, sublicense, and distribute the
 | 
			
		||||
      Work and such Derivative Works in Source or Object form.
 | 
			
		||||
 | 
			
		||||
   3. Grant of Patent License. Subject to the terms and conditions of
 | 
			
		||||
      this License, each Contributor hereby grants to You a perpetual,
 | 
			
		||||
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
 | 
			
		||||
      (except as stated in this section) patent license to make, have made,
 | 
			
		||||
      use, offer to sell, sell, import, and otherwise transfer the Work,
 | 
			
		||||
      where such license applies only to those patent claims licensable
 | 
			
		||||
      by such Contributor that are necessarily infringed by their
 | 
			
		||||
      Contribution(s) alone or by combination of their Contribution(s)
 | 
			
		||||
      with the Work to which such Contribution(s) was submitted. If You
 | 
			
		||||
      institute patent litigation against any entity (including a
 | 
			
		||||
      cross-claim or counterclaim in a lawsuit) alleging that the Work
 | 
			
		||||
      or a Contribution incorporated within the Work constitutes direct
 | 
			
		||||
      or contributory patent infringement, then any patent licenses
 | 
			
		||||
      granted to You under this License for that Work shall terminate
 | 
			
		||||
      as of the date such litigation is filed.
 | 
			
		||||
 | 
			
		||||
   4. Redistribution. You may reproduce and distribute copies of the
 | 
			
		||||
      Work or Derivative Works thereof in any medium, with or without
 | 
			
		||||
      modifications, and in Source or Object form, provided that You
 | 
			
		||||
      meet the following conditions:
 | 
			
		||||
 | 
			
		||||
      (a) You must give any other recipients of the Work or
 | 
			
		||||
          Derivative Works a copy of this License; and
 | 
			
		||||
 | 
			
		||||
      (b) You must cause any modified files to carry prominent notices
 | 
			
		||||
          stating that You changed the files; and
 | 
			
		||||
 | 
			
		||||
      (c) You must retain, in the Source form of any Derivative Works
 | 
			
		||||
          that You distribute, all copyright, patent, trademark, and
 | 
			
		||||
          attribution notices from the Source form of the Work,
 | 
			
		||||
          excluding those notices that do not pertain to any part of
 | 
			
		||||
          the Derivative Works; and
 | 
			
		||||
 | 
			
		||||
      (d) If the Work includes a "NOTICE" text file as part of its
 | 
			
		||||
          distribution, then any Derivative Works that You distribute must
 | 
			
		||||
          include a readable copy of the attribution notices contained
 | 
			
		||||
          within such NOTICE file, excluding those notices that do not
 | 
			
		||||
          pertain to any part of the Derivative Works, in at least one
 | 
			
		||||
          of the following places: within a NOTICE text file distributed
 | 
			
		||||
          as part of the Derivative Works; within the Source form or
 | 
			
		||||
          documentation, if provided along with the Derivative Works; or,
 | 
			
		||||
          within a display generated by the Derivative Works, if and
 | 
			
		||||
          wherever such third-party notices normally appear. The contents
 | 
			
		||||
          of the NOTICE file are for informational purposes only and
 | 
			
		||||
          do not modify the License. You may add Your own attribution
 | 
			
		||||
          notices within Derivative Works that You distribute, alongside
 | 
			
		||||
          or as an addendum to the NOTICE text from the Work, provided
 | 
			
		||||
          that such additional attribution notices cannot be construed
 | 
			
		||||
          as modifying the License.
 | 
			
		||||
 | 
			
		||||
      You may add Your own copyright statement to Your modifications and
 | 
			
		||||
      may provide additional or different license terms and conditions
 | 
			
		||||
      for use, reproduction, or distribution of Your modifications, or
 | 
			
		||||
      for any such Derivative Works as a whole, provided Your use,
 | 
			
		||||
      reproduction, and distribution of the Work otherwise complies with
 | 
			
		||||
      the conditions stated in this License.
 | 
			
		||||
 | 
			
		||||
   5. Submission of Contributions. Unless You explicitly state otherwise,
 | 
			
		||||
      any Contribution intentionally submitted for inclusion in the Work
 | 
			
		||||
      by You to the Licensor shall be under the terms and conditions of
 | 
			
		||||
      this License, without any additional terms or conditions.
 | 
			
		||||
      Notwithstanding the above, nothing herein shall supersede or modify
 | 
			
		||||
      the terms of any separate license agreement you may have executed
 | 
			
		||||
      with Licensor regarding such Contributions.
 | 
			
		||||
 | 
			
		||||
   6. Trademarks. This License does not grant permission to use the trade
 | 
			
		||||
      names, trademarks, service marks, or product names of the Licensor,
 | 
			
		||||
      except as required for reasonable and customary use in describing the
 | 
			
		||||
      origin of the Work and reproducing the content of the NOTICE file.
 | 
			
		||||
 | 
			
		||||
   7. Disclaimer of Warranty. Unless required by applicable law or
 | 
			
		||||
      agreed to in writing, Licensor provides the Work (and each
 | 
			
		||||
      Contributor provides its Contributions) on an "AS IS" BASIS,
 | 
			
		||||
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
 | 
			
		||||
      implied, including, without limitation, any warranties or conditions
 | 
			
		||||
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
 | 
			
		||||
      PARTICULAR PURPOSE. You are solely responsible for determining the
 | 
			
		||||
      appropriateness of using or redistributing the Work and assume any
 | 
			
		||||
      risks associated with Your exercise of permissions under this License.
 | 
			
		||||
 | 
			
		||||
   8. Limitation of Liability. In no event and under no legal theory,
 | 
			
		||||
      whether in tort (including negligence), contract, or otherwise,
 | 
			
		||||
      unless required by applicable law (such as deliberate and grossly
 | 
			
		||||
      negligent acts) or agreed to in writing, shall any Contributor be
 | 
			
		||||
      liable to You for damages, including any direct, indirect, special,
 | 
			
		||||
      incidental, or consequential damages of any character arising as a
 | 
			
		||||
      result of this License or out of the use or inability to use the
 | 
			
		||||
      Work (including but not limited to damages for loss of goodwill,
 | 
			
		||||
      work stoppage, computer failure or malfunction, or any and all
 | 
			
		||||
      other commercial damages or losses), even if such Contributor
 | 
			
		||||
      has been advised of the possibility of such damages.
 | 
			
		||||
 | 
			
		||||
   9. Accepting Warranty or Additional Liability. While redistributing
 | 
			
		||||
      the Work or Derivative Works thereof, You may choose to offer,
 | 
			
		||||
      and charge a fee for, acceptance of support, warranty, indemnity,
 | 
			
		||||
      or other liability obligations and/or rights consistent with this
 | 
			
		||||
      License. However, in accepting such obligations, You may act only
 | 
			
		||||
      on Your own behalf and on Your sole responsibility, not on behalf
 | 
			
		||||
      of any other Contributor, and only if You agree to indemnify,
 | 
			
		||||
      defend, and hold each Contributor harmless for any liability
 | 
			
		||||
      incurred by, or claims asserted against, such Contributor by reason
 | 
			
		||||
      of your accepting any such warranty or additional liability.
 | 
			
		||||
 | 
			
		||||
   END OF TERMS AND CONDITIONS
 | 
			
		||||
 | 
			
		||||
   APPENDIX: How to apply the Apache License to your work.
 | 
			
		||||
 | 
			
		||||
      To apply the Apache License to your work, attach the following
 | 
			
		||||
      boilerplate notice, with the fields enclosed by brackets "[]"
 | 
			
		||||
      replaced with your own identifying information. (Don't include
 | 
			
		||||
      the brackets!)  The text should be enclosed in the appropriate
 | 
			
		||||
      comment syntax for the file format. We also recommend that a
 | 
			
		||||
      file or class name and description of purpose be included on the
 | 
			
		||||
      same "printed page" as the copyright notice for easier
 | 
			
		||||
      identification within third-party archives.
 | 
			
		||||
 | 
			
		||||
   Copyright [yyyy] [name of copyright owner]
 | 
			
		||||
 | 
			
		||||
   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.
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/pelletier/go-toml/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/pelletier/go-toml/Makefile
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,29 +0,0 @@
 | 
			
		||||
export CGO_ENABLED=0
 | 
			
		||||
go := go
 | 
			
		||||
go.goos ?= $(shell echo `go version`|cut -f4 -d ' '|cut -d '/' -f1)
 | 
			
		||||
go.goarch ?= $(shell echo `go version`|cut -f4 -d ' '|cut -d '/' -f2)
 | 
			
		||||
 | 
			
		||||
out.tools := tomll tomljson jsontoml
 | 
			
		||||
out.dist := $(out.tools:=_$(go.goos)_$(go.goarch).tar.xz)
 | 
			
		||||
sources := $(wildcard **/*.go)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.PHONY:
 | 
			
		||||
tools: $(out.tools)
 | 
			
		||||
 | 
			
		||||
$(out.tools): $(sources)
 | 
			
		||||
	GOOS=$(go.goos) GOARCH=$(go.goarch) $(go) build ./cmd/$@
 | 
			
		||||
 | 
			
		||||
.PHONY:
 | 
			
		||||
dist: $(out.dist)
 | 
			
		||||
 | 
			
		||||
$(out.dist):%_$(go.goos)_$(go.goarch).tar.xz: %
 | 
			
		||||
	if [ "$(go.goos)" = "windows" ]; then \
 | 
			
		||||
		tar -cJf $@ $^.exe; \
 | 
			
		||||
	else \
 | 
			
		||||
		tar -cJf $@ $^; \
 | 
			
		||||
	fi
 | 
			
		||||
 | 
			
		||||
.PHONY:
 | 
			
		||||
clean:
 | 
			
		||||
	rm -rf $(out.tools) $(out.dist)
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/pelletier/go-toml/PULL_REQUEST_TEMPLATE.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,5 +0,0 @@
 | 
			
		||||
**Issue:** add link to pelletier/go-toml issue here
 | 
			
		||||
 | 
			
		||||
Explanation of what this pull request does.
 | 
			
		||||
 | 
			
		||||
More detailed description of the decisions being made and the reasons why (if the patch is non-trivial).
 | 
			
		||||
							
								
								
									
										176
									
								
								vendor/github.com/pelletier/go-toml/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										176
									
								
								vendor/github.com/pelletier/go-toml/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,176 +0,0 @@
 | 
			
		||||
# go-toml
 | 
			
		||||
 | 
			
		||||
Go library for the [TOML](https://toml.io/) format.
 | 
			
		||||
 | 
			
		||||
This library supports TOML version
 | 
			
		||||
[v1.0.0-rc.3](https://toml.io/en/v1.0.0-rc.3)
 | 
			
		||||
 | 
			
		||||
[](https://pkg.go.dev/github.com/pelletier/go-toml)
 | 
			
		||||
[](https://github.com/pelletier/go-toml/blob/master/LICENSE)
 | 
			
		||||
[](https://dev.azure.com/pelletierthomas/go-toml-ci/_build/latest?definitionId=1&branchName=master)
 | 
			
		||||
[](https://codecov.io/gh/pelletier/go-toml)
 | 
			
		||||
[](https://goreportcard.com/report/github.com/pelletier/go-toml)
 | 
			
		||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fpelletier%2Fgo-toml?ref=badge_shield)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
## Development status
 | 
			
		||||
 | 
			
		||||
**ℹ️ Consider go-toml v2!**
 | 
			
		||||
 | 
			
		||||
The next version of go-toml is in [active development][v2-dev], and
 | 
			
		||||
[nearing completion][v2-map].
 | 
			
		||||
 | 
			
		||||
Though technically in beta, v2 is already more tested, [fixes bugs][v1-bugs],
 | 
			
		||||
and [much faster][v2-bench]. If you only need reading and writing TOML documents
 | 
			
		||||
(majority of cases), those features are implemented and the API unlikely to
 | 
			
		||||
change.
 | 
			
		||||
 | 
			
		||||
The remaining features will be added shortly. While pull-requests are welcome on
 | 
			
		||||
v1, no active development is expected on it. When v2.0.0 is released, v1 will be
 | 
			
		||||
deprecated.
 | 
			
		||||
 | 
			
		||||
👉 [go-toml v2][v2]
 | 
			
		||||
 | 
			
		||||
[v2]: https://github.com/pelletier/go-toml/tree/v2
 | 
			
		||||
[v2-map]: https://github.com/pelletier/go-toml/discussions/506
 | 
			
		||||
[v2-dev]: https://github.com/pelletier/go-toml/tree/v2
 | 
			
		||||
[v1-bugs]: https://github.com/pelletier/go-toml/issues?q=is%3Aissue+is%3Aopen+label%3Av2-fixed
 | 
			
		||||
[v2-bench]: https://github.com/pelletier/go-toml/tree/v2#benchmarks
 | 
			
		||||
 | 
			
		||||
## Features
 | 
			
		||||
 | 
			
		||||
Go-toml provides the following features for using data parsed from TOML documents:
 | 
			
		||||
 | 
			
		||||
* Load TOML documents from files and string data
 | 
			
		||||
* Easily navigate TOML structure using Tree
 | 
			
		||||
* Marshaling and unmarshaling to and from data structures
 | 
			
		||||
* Line & column position data for all parsed elements
 | 
			
		||||
* [Query support similar to JSON-Path](query/)
 | 
			
		||||
* Syntax errors contain line and column numbers
 | 
			
		||||
 | 
			
		||||
## Import
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
import "github.com/pelletier/go-toml"
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Usage example
 | 
			
		||||
 | 
			
		||||
Read a TOML document:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
config, _ := toml.Load(`
 | 
			
		||||
[postgres]
 | 
			
		||||
user = "pelletier"
 | 
			
		||||
password = "mypassword"`)
 | 
			
		||||
// retrieve data directly
 | 
			
		||||
user := config.Get("postgres.user").(string)
 | 
			
		||||
 | 
			
		||||
// or using an intermediate object
 | 
			
		||||
postgresConfig := config.Get("postgres").(*toml.Tree)
 | 
			
		||||
password := postgresConfig.Get("password").(string)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or use Unmarshal:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
type Postgres struct {
 | 
			
		||||
    User     string
 | 
			
		||||
    Password string
 | 
			
		||||
}
 | 
			
		||||
type Config struct {
 | 
			
		||||
    Postgres Postgres
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
doc := []byte(`
 | 
			
		||||
[Postgres]
 | 
			
		||||
User = "pelletier"
 | 
			
		||||
Password = "mypassword"`)
 | 
			
		||||
 | 
			
		||||
config := Config{}
 | 
			
		||||
toml.Unmarshal(doc, &config)
 | 
			
		||||
fmt.Println("user=", config.Postgres.User)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Or use a query:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
// use a query to gather elements without walking the tree
 | 
			
		||||
q, _ := query.Compile("$..[user,password]")
 | 
			
		||||
results := q.Execute(config)
 | 
			
		||||
for ii, item := range results.Values() {
 | 
			
		||||
    fmt.Printf("Query result %d: %v\n", ii, item)
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
The documentation and additional examples are available at
 | 
			
		||||
[pkg.go.dev](https://pkg.go.dev/github.com/pelletier/go-toml).
 | 
			
		||||
 | 
			
		||||
## Tools
 | 
			
		||||
 | 
			
		||||
Go-toml provides three handy command line tools:
 | 
			
		||||
 | 
			
		||||
* `tomll`: Reads TOML files and lints them.
 | 
			
		||||
 | 
			
		||||
    ```
 | 
			
		||||
    go install github.com/pelletier/go-toml/cmd/tomll
 | 
			
		||||
    tomll --help
 | 
			
		||||
    ```
 | 
			
		||||
* `tomljson`: Reads a TOML file and outputs its JSON representation.
 | 
			
		||||
 | 
			
		||||
    ```
 | 
			
		||||
    go install github.com/pelletier/go-toml/cmd/tomljson
 | 
			
		||||
    tomljson --help
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
 * `jsontoml`: Reads a JSON file and outputs a TOML representation.
 | 
			
		||||
 | 
			
		||||
    ```
 | 
			
		||||
    go install github.com/pelletier/go-toml/cmd/jsontoml
 | 
			
		||||
    jsontoml --help
 | 
			
		||||
    ```
 | 
			
		||||
 | 
			
		||||
### Docker image
 | 
			
		||||
 | 
			
		||||
Those tools are also available as a Docker image from
 | 
			
		||||
[dockerhub](https://hub.docker.com/r/pelletier/go-toml). For example, to
 | 
			
		||||
use `tomljson`:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
docker run -v $PWD:/workdir pelletier/go-toml tomljson /workdir/example.toml
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Only master (`latest`) and tagged versions are published to dockerhub. You
 | 
			
		||||
can build your own image as usual:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
docker build -t go-toml .
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
## Contribute
 | 
			
		||||
 | 
			
		||||
Feel free to report bugs and patches using GitHub's pull requests system on
 | 
			
		||||
[pelletier/go-toml](https://github.com/pelletier/go-toml). Any feedback would be
 | 
			
		||||
much appreciated!
 | 
			
		||||
 | 
			
		||||
### Run tests
 | 
			
		||||
 | 
			
		||||
`go test ./...`
 | 
			
		||||
 | 
			
		||||
### Fuzzing
 | 
			
		||||
 | 
			
		||||
The script `./fuzz.sh` is available to
 | 
			
		||||
run [go-fuzz](https://github.com/dvyukov/go-fuzz) on go-toml.
 | 
			
		||||
 | 
			
		||||
## 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) + Apache 2.0. Read [LICENSE](LICENSE).
 | 
			
		||||
							
								
								
									
										188
									
								
								vendor/github.com/pelletier/go-toml/azure-pipelines.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										188
									
								
								vendor/github.com/pelletier/go-toml/azure-pipelines.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,188 +0,0 @@
 | 
			
		||||
trigger:
 | 
			
		||||
- master
 | 
			
		||||
 | 
			
		||||
stages:
 | 
			
		||||
- stage: run_checks
 | 
			
		||||
  displayName: "Check"
 | 
			
		||||
  dependsOn: []
 | 
			
		||||
  jobs:
 | 
			
		||||
  - job: fmt
 | 
			
		||||
    displayName: "fmt"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: GoTool@0
 | 
			
		||||
      displayName: "Install Go 1.16"
 | 
			
		||||
      inputs:
 | 
			
		||||
        version: "1.16"
 | 
			
		||||
    - task: Go@0
 | 
			
		||||
      displayName: "go fmt ./..."
 | 
			
		||||
      inputs:
 | 
			
		||||
        command: 'custom'
 | 
			
		||||
        customCommand: 'fmt'
 | 
			
		||||
        arguments: './...'
 | 
			
		||||
  - job: coverage
 | 
			
		||||
    displayName: "coverage"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: GoTool@0
 | 
			
		||||
      displayName: "Install Go 1.16"
 | 
			
		||||
      inputs:
 | 
			
		||||
        version: "1.16"
 | 
			
		||||
    - task: Go@0
 | 
			
		||||
      displayName: "Generate coverage"
 | 
			
		||||
      inputs:
 | 
			
		||||
        command: 'test'
 | 
			
		||||
        arguments: "-race -coverprofile=coverage.txt -covermode=atomic"
 | 
			
		||||
    - task: Bash@3
 | 
			
		||||
      inputs:
 | 
			
		||||
        targetType: 'inline'
 | 
			
		||||
        script: 'bash <(curl -s https://codecov.io/bash) -t ${CODECOV_TOKEN}'
 | 
			
		||||
      env:
 | 
			
		||||
        CODECOV_TOKEN: $(CODECOV_TOKEN)
 | 
			
		||||
  - job: benchmark
 | 
			
		||||
    displayName: "benchmark"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: GoTool@0
 | 
			
		||||
      displayName: "Install Go 1.16"
 | 
			
		||||
      inputs:
 | 
			
		||||
        version: "1.16"
 | 
			
		||||
    - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/"
 | 
			
		||||
    - task: Bash@3
 | 
			
		||||
      inputs:
 | 
			
		||||
        filePath: './benchmark.sh'
 | 
			
		||||
        arguments: "master $(Build.Repository.Uri)"
 | 
			
		||||
 | 
			
		||||
  - job: go_unit_tests
 | 
			
		||||
    displayName: "unit tests"
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        linux 1.16:
 | 
			
		||||
          goVersion: '1.16'
 | 
			
		||||
          imageName: 'ubuntu-latest'
 | 
			
		||||
        mac 1.16:
 | 
			
		||||
          goVersion: '1.16'
 | 
			
		||||
          imageName: 'macOS-latest'
 | 
			
		||||
        windows 1.16:
 | 
			
		||||
          goVersion: '1.16'
 | 
			
		||||
          imageName: 'windows-latest'
 | 
			
		||||
        linux 1.15:
 | 
			
		||||
          goVersion: '1.15'
 | 
			
		||||
          imageName: 'ubuntu-latest'
 | 
			
		||||
        mac 1.15:
 | 
			
		||||
          goVersion: '1.15'
 | 
			
		||||
          imageName: 'macOS-latest'
 | 
			
		||||
        windows 1.15:
 | 
			
		||||
          goVersion: '1.15'
 | 
			
		||||
          imageName: 'windows-latest'
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: $(imageName)
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: GoTool@0
 | 
			
		||||
      displayName: "Install Go $(goVersion)"
 | 
			
		||||
      inputs:
 | 
			
		||||
        version: $(goVersion)
 | 
			
		||||
    - task: Go@0
 | 
			
		||||
      displayName: "go test ./..."
 | 
			
		||||
      inputs:
 | 
			
		||||
        command: 'test'
 | 
			
		||||
        arguments: './...'
 | 
			
		||||
- stage: build_binaries
 | 
			
		||||
  displayName: "Build binaries"
 | 
			
		||||
  dependsOn: run_checks
 | 
			
		||||
  jobs:
 | 
			
		||||
  - job: build_binary
 | 
			
		||||
    displayName: "Build binary"
 | 
			
		||||
    strategy:
 | 
			
		||||
      matrix:
 | 
			
		||||
        linux_amd64:
 | 
			
		||||
          GOOS: linux
 | 
			
		||||
          GOARCH: amd64
 | 
			
		||||
        darwin_amd64:
 | 
			
		||||
          GOOS: darwin
 | 
			
		||||
          GOARCH: amd64
 | 
			
		||||
        windows_amd64:
 | 
			
		||||
          GOOS: windows
 | 
			
		||||
          GOARCH: amd64
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: GoTool@0
 | 
			
		||||
      displayName: "Install Go"
 | 
			
		||||
      inputs:
 | 
			
		||||
        version: 1.16
 | 
			
		||||
    - task: Bash@3
 | 
			
		||||
      inputs:
 | 
			
		||||
        targetType: inline
 | 
			
		||||
        script: "make dist"
 | 
			
		||||
      env:
 | 
			
		||||
        go.goos: $(GOOS)
 | 
			
		||||
        go.goarch: $(GOARCH)
 | 
			
		||||
    - task: CopyFiles@2
 | 
			
		||||
      inputs:
 | 
			
		||||
        sourceFolder: '$(Build.SourcesDirectory)'
 | 
			
		||||
        contents: '*.tar.xz'
 | 
			
		||||
        TargetFolder: '$(Build.ArtifactStagingDirectory)'
 | 
			
		||||
    - task: PublishBuildArtifacts@1
 | 
			
		||||
      inputs:
 | 
			
		||||
        pathtoPublish: '$(Build.ArtifactStagingDirectory)'
 | 
			
		||||
        artifactName: binaries
 | 
			
		||||
- stage: build_binaries_manifest
 | 
			
		||||
  displayName: "Build binaries manifest"
 | 
			
		||||
  dependsOn: build_binaries
 | 
			
		||||
  jobs:
 | 
			
		||||
  - job: build_manifest
 | 
			
		||||
    displayName: "Build binaries manifest"
 | 
			
		||||
    steps:
 | 
			
		||||
      - task: DownloadBuildArtifacts@0
 | 
			
		||||
        inputs:
 | 
			
		||||
          buildType: 'current'
 | 
			
		||||
          downloadType: 'single'
 | 
			
		||||
          artifactName: 'binaries'
 | 
			
		||||
          downloadPath: '$(Build.SourcesDirectory)'
 | 
			
		||||
      - task: Bash@3
 | 
			
		||||
        inputs:
 | 
			
		||||
          targetType: inline
 | 
			
		||||
          script: "cd binaries && sha256sum --binary *.tar.xz | tee $(Build.ArtifactStagingDirectory)/sha256sums.txt"
 | 
			
		||||
      - task: PublishBuildArtifacts@1
 | 
			
		||||
        inputs:
 | 
			
		||||
          pathtoPublish: '$(Build.ArtifactStagingDirectory)'
 | 
			
		||||
          artifactName: manifest
 | 
			
		||||
 | 
			
		||||
- stage: build_docker_image
 | 
			
		||||
  displayName: "Build Docker image"
 | 
			
		||||
  dependsOn: run_checks
 | 
			
		||||
  jobs:
 | 
			
		||||
  - job: build
 | 
			
		||||
    displayName: "Build"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: Docker@2
 | 
			
		||||
      inputs:
 | 
			
		||||
        command: 'build'
 | 
			
		||||
        Dockerfile: 'Dockerfile'
 | 
			
		||||
        buildContext: '.'
 | 
			
		||||
        addPipelineData: false
 | 
			
		||||
 | 
			
		||||
- stage: publish_docker_image
 | 
			
		||||
  displayName: "Publish Docker image"
 | 
			
		||||
  dependsOn: build_docker_image
 | 
			
		||||
  condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'master'))
 | 
			
		||||
  jobs:
 | 
			
		||||
  - job: publish
 | 
			
		||||
    displayName: "Publish"
 | 
			
		||||
    pool:
 | 
			
		||||
      vmImage: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
    - task: Docker@2
 | 
			
		||||
      inputs:
 | 
			
		||||
        containerRegistry: 'DockerHub'
 | 
			
		||||
        repository: 'pelletier/go-toml'
 | 
			
		||||
        command: 'buildAndPush'
 | 
			
		||||
        Dockerfile: 'Dockerfile'
 | 
			
		||||
        buildContext: '.'
 | 
			
		||||
        tags: 'latest'
 | 
			
		||||
							
								
								
									
										35
									
								
								vendor/github.com/pelletier/go-toml/benchmark.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								vendor/github.com/pelletier/go-toml/benchmark.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,35 +0,0 @@
 | 
			
		||||
#!/bin/bash
 | 
			
		||||
 | 
			
		||||
set -ex
 | 
			
		||||
 | 
			
		||||
reference_ref=${1:-master}
 | 
			
		||||
reference_git=${2:-.}
 | 
			
		||||
 | 
			
		||||
if ! `hash benchstat 2>/dev/null`; then
 | 
			
		||||
    echo "Installing benchstat"
 | 
			
		||||
    go get golang.org/x/perf/cmd/benchstat
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX`
 | 
			
		||||
ref_tempdir="${tempdir}/ref"
 | 
			
		||||
ref_benchmark="${ref_tempdir}/benchmark-`echo -n ${reference_ref}|tr -s '/' '-'`.txt"
 | 
			
		||||
local_benchmark="`pwd`/benchmark-local.txt"
 | 
			
		||||
 | 
			
		||||
echo "=== ${reference_ref} (${ref_tempdir})"
 | 
			
		||||
git clone ${reference_git} ${ref_tempdir} >/dev/null 2>/dev/null
 | 
			
		||||
pushd ${ref_tempdir} >/dev/null
 | 
			
		||||
git checkout ${reference_ref} >/dev/null 2>/dev/null
 | 
			
		||||
go test -bench=. -benchmem | tee ${ref_benchmark}
 | 
			
		||||
cd benchmark
 | 
			
		||||
go test -bench=. -benchmem | tee -a ${ref_benchmark}
 | 
			
		||||
popd >/dev/null
 | 
			
		||||
 | 
			
		||||
echo ""
 | 
			
		||||
echo "=== local"
 | 
			
		||||
go test -bench=. -benchmem  | tee ${local_benchmark}
 | 
			
		||||
cd benchmark
 | 
			
		||||
go test -bench=. -benchmem | tee -a ${local_benchmark}
 | 
			
		||||
 | 
			
		||||
echo ""
 | 
			
		||||
echo "=== diff"
 | 
			
		||||
benchstat -delta-test=none ${ref_benchmark} ${local_benchmark}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/pelletier/go-toml/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/pelletier/go-toml/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,23 +0,0 @@
 | 
			
		||||
// Package toml is a TOML parser and manipulation library.
 | 
			
		||||
//
 | 
			
		||||
// This version supports the specification as described in
 | 
			
		||||
// https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md
 | 
			
		||||
//
 | 
			
		||||
// Marshaling
 | 
			
		||||
//
 | 
			
		||||
// Go-toml can marshal and unmarshal TOML documents from and to data
 | 
			
		||||
// structures.
 | 
			
		||||
//
 | 
			
		||||
// TOML document as a tree
 | 
			
		||||
//
 | 
			
		||||
// Go-toml can operate on a TOML document as a tree. Use one of the Load*
 | 
			
		||||
// functions to parse TOML data and obtain a Tree instance, then one of its
 | 
			
		||||
// methods to manipulate the tree.
 | 
			
		||||
//
 | 
			
		||||
// JSONPath-like queries
 | 
			
		||||
//
 | 
			
		||||
// The package github.com/pelletier/go-toml/query implements a system
 | 
			
		||||
// similar to JSONPath to quickly retrieve elements of a TOML document using a
 | 
			
		||||
// single expression. See the package documentation for more information.
 | 
			
		||||
//
 | 
			
		||||
package toml
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/pelletier/go-toml/example-crlf.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/pelletier/go-toml/example-crlf.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,30 +0,0 @@
 | 
			
		||||
# This is a TOML document. Boom.
 | 
			
		||||
 | 
			
		||||
title = "TOML Example"
 | 
			
		||||
 | 
			
		||||
[owner]
 | 
			
		||||
name = "Tom Preston-Werner"
 | 
			
		||||
organization = "GitHub"
 | 
			
		||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
 | 
			
		||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
 | 
			
		||||
 | 
			
		||||
[database]
 | 
			
		||||
server = "192.168.1.1"
 | 
			
		||||
ports = [ 8001, 8001, 8002 ]
 | 
			
		||||
connection_max = 5000
 | 
			
		||||
enabled = true
 | 
			
		||||
 | 
			
		||||
[servers]
 | 
			
		||||
 | 
			
		||||
  # You can indent as you please. Tabs or spaces. TOML don't care.
 | 
			
		||||
  [servers.alpha]
 | 
			
		||||
  ip = "10.0.0.1"
 | 
			
		||||
  dc = "eqdc10"
 | 
			
		||||
 | 
			
		||||
  [servers.beta]
 | 
			
		||||
  ip = "10.0.0.2"
 | 
			
		||||
  dc = "eqdc10"
 | 
			
		||||
 | 
			
		||||
[clients]
 | 
			
		||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
 | 
			
		||||
score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported
 | 
			
		||||
							
								
								
									
										30
									
								
								vendor/github.com/pelletier/go-toml/example.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										30
									
								
								vendor/github.com/pelletier/go-toml/example.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,30 +0,0 @@
 | 
			
		||||
# This is a TOML document. Boom.
 | 
			
		||||
 | 
			
		||||
title = "TOML Example"
 | 
			
		||||
 | 
			
		||||
[owner]
 | 
			
		||||
name = "Tom Preston-Werner"
 | 
			
		||||
organization = "GitHub"
 | 
			
		||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
 | 
			
		||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
 | 
			
		||||
 | 
			
		||||
[database]
 | 
			
		||||
server = "192.168.1.1"
 | 
			
		||||
ports = [ 8001, 8001, 8002 ]
 | 
			
		||||
connection_max = 5000
 | 
			
		||||
enabled = true
 | 
			
		||||
 | 
			
		||||
[servers]
 | 
			
		||||
 | 
			
		||||
  # You can indent as you please. Tabs or spaces. TOML don't care.
 | 
			
		||||
  [servers.alpha]
 | 
			
		||||
  ip = "10.0.0.1"
 | 
			
		||||
  dc = "eqdc10"
 | 
			
		||||
 | 
			
		||||
  [servers.beta]
 | 
			
		||||
  ip = "10.0.0.2"
 | 
			
		||||
  dc = "eqdc10"
 | 
			
		||||
 | 
			
		||||
[clients]
 | 
			
		||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
 | 
			
		||||
score = 4e-08 # to make sure leading zeroes in exponent parts of floats are supported
 | 
			
		||||
							
								
								
									
										31
									
								
								vendor/github.com/pelletier/go-toml/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										31
									
								
								vendor/github.com/pelletier/go-toml/fuzz.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,31 +0,0 @@
 | 
			
		||||
// +build gofuzz
 | 
			
		||||
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
func Fuzz(data []byte) int {
 | 
			
		||||
	tree, err := LoadBytes(data)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if tree != nil {
 | 
			
		||||
			panic("tree must be nil if there is an error")
 | 
			
		||||
		}
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	str, err := tree.ToTomlString()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if str != "" {
 | 
			
		||||
			panic(`str must be "" if there is an error`)
 | 
			
		||||
		}
 | 
			
		||||
		panic(err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tree, err = Load(str)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		if tree != nil {
 | 
			
		||||
			panic("tree must be nil if there is an error")
 | 
			
		||||
		}
 | 
			
		||||
		return 0
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return 1
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										15
									
								
								vendor/github.com/pelletier/go-toml/fuzz.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										15
									
								
								vendor/github.com/pelletier/go-toml/fuzz.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,15 +0,0 @@
 | 
			
		||||
#! /bin/sh
 | 
			
		||||
set -eu
 | 
			
		||||
 | 
			
		||||
go get github.com/dvyukov/go-fuzz/go-fuzz
 | 
			
		||||
go get github.com/dvyukov/go-fuzz/go-fuzz-build
 | 
			
		||||
 | 
			
		||||
if [ ! -e toml-fuzz.zip ]; then
 | 
			
		||||
    go-fuzz-build github.com/pelletier/go-toml
 | 
			
		||||
fi
 | 
			
		||||
 | 
			
		||||
rm -fr fuzz
 | 
			
		||||
mkdir -p fuzz/corpus
 | 
			
		||||
cp *.toml fuzz/corpus
 | 
			
		||||
 | 
			
		||||
go-fuzz -bin=toml-fuzz.zip -workdir=fuzz
 | 
			
		||||
							
								
								
									
										112
									
								
								vendor/github.com/pelletier/go-toml/keysparsing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										112
									
								
								vendor/github.com/pelletier/go-toml/keysparsing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,112 +0,0 @@
 | 
			
		||||
// Parsing keys handling both bare and quoted keys.
 | 
			
		||||
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Convert the bare key group string to an array.
 | 
			
		||||
// The input supports double quotation and single quotation,
 | 
			
		||||
// but escape sequences are not supported. Lexers must unescape them beforehand.
 | 
			
		||||
func parseKey(key string) ([]string, error) {
 | 
			
		||||
	runes := []rune(key)
 | 
			
		||||
	var groups []string
 | 
			
		||||
 | 
			
		||||
	if len(key) == 0 {
 | 
			
		||||
		return nil, errors.New("empty key")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	idx := 0
 | 
			
		||||
	for idx < len(runes) {
 | 
			
		||||
		for ; idx < len(runes) && isSpace(runes[idx]); idx++ {
 | 
			
		||||
			// skip leading whitespace
 | 
			
		||||
		}
 | 
			
		||||
		if idx >= len(runes) {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		r := runes[idx]
 | 
			
		||||
		if isValidBareChar(r) {
 | 
			
		||||
			// parse bare key
 | 
			
		||||
			startIdx := idx
 | 
			
		||||
			endIdx := -1
 | 
			
		||||
			idx++
 | 
			
		||||
			for idx < len(runes) {
 | 
			
		||||
				r = runes[idx]
 | 
			
		||||
				if isValidBareChar(r) {
 | 
			
		||||
					idx++
 | 
			
		||||
				} else if r == '.' {
 | 
			
		||||
					endIdx = idx
 | 
			
		||||
					break
 | 
			
		||||
				} else if isSpace(r) {
 | 
			
		||||
					endIdx = idx
 | 
			
		||||
					for ; idx < len(runes) && isSpace(runes[idx]); idx++ {
 | 
			
		||||
						// skip trailing whitespace
 | 
			
		||||
					}
 | 
			
		||||
					if idx < len(runes) && runes[idx] != '.' {
 | 
			
		||||
						return nil, fmt.Errorf("invalid key character after whitespace: %c", runes[idx])
 | 
			
		||||
					}
 | 
			
		||||
					break
 | 
			
		||||
				} else {
 | 
			
		||||
					return nil, fmt.Errorf("invalid bare key character: %c", r)
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if endIdx == -1 {
 | 
			
		||||
				endIdx = idx
 | 
			
		||||
			}
 | 
			
		||||
			groups = append(groups, string(runes[startIdx:endIdx]))
 | 
			
		||||
		} else if r == '\'' {
 | 
			
		||||
			// parse single quoted key
 | 
			
		||||
			idx++
 | 
			
		||||
			startIdx := idx
 | 
			
		||||
			for {
 | 
			
		||||
				if idx >= len(runes) {
 | 
			
		||||
					return nil, fmt.Errorf("unclosed single-quoted key")
 | 
			
		||||
				}
 | 
			
		||||
				r = runes[idx]
 | 
			
		||||
				if r == '\'' {
 | 
			
		||||
					groups = append(groups, string(runes[startIdx:idx]))
 | 
			
		||||
					idx++
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				idx++
 | 
			
		||||
			}
 | 
			
		||||
		} else if r == '"' {
 | 
			
		||||
			// parse double quoted key
 | 
			
		||||
			idx++
 | 
			
		||||
			startIdx := idx
 | 
			
		||||
			for {
 | 
			
		||||
				if idx >= len(runes) {
 | 
			
		||||
					return nil, fmt.Errorf("unclosed double-quoted key")
 | 
			
		||||
				}
 | 
			
		||||
				r = runes[idx]
 | 
			
		||||
				if r == '"' {
 | 
			
		||||
					groups = append(groups, string(runes[startIdx:idx]))
 | 
			
		||||
					idx++
 | 
			
		||||
					break
 | 
			
		||||
				}
 | 
			
		||||
				idx++
 | 
			
		||||
			}
 | 
			
		||||
		} else if r == '.' {
 | 
			
		||||
			idx++
 | 
			
		||||
			if idx >= len(runes) {
 | 
			
		||||
				return nil, fmt.Errorf("unexpected end of key")
 | 
			
		||||
			}
 | 
			
		||||
			r = runes[idx]
 | 
			
		||||
			if !isValidBareChar(r) && r != '\'' && r != '"' && r != ' ' {
 | 
			
		||||
				return nil, fmt.Errorf("expecting key part after dot")
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
			return nil, fmt.Errorf("invalid key character: %c", r)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(groups) == 0 {
 | 
			
		||||
		return nil, fmt.Errorf("empty key")
 | 
			
		||||
	}
 | 
			
		||||
	return groups, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isValidBareChar(r rune) bool {
 | 
			
		||||
	return isAlphanumeric(r) || r == '-' || isDigit(r)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1031
									
								
								vendor/github.com/pelletier/go-toml/lexer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1031
									
								
								vendor/github.com/pelletier/go-toml/lexer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										287
									
								
								vendor/github.com/pelletier/go-toml/localtime.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										287
									
								
								vendor/github.com/pelletier/go-toml/localtime.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,287 +0,0 @@
 | 
			
		||||
// Implementation of TOML's local date/time.
 | 
			
		||||
//
 | 
			
		||||
// Copied over from Google's civil to avoid pulling all the Google dependencies.
 | 
			
		||||
// Originals:
 | 
			
		||||
//   https://raw.githubusercontent.com/googleapis/google-cloud-go/ed46f5086358513cf8c25f8e3f022cb838a49d66/civil/civil.go
 | 
			
		||||
// Changes:
 | 
			
		||||
//   * Renamed files from civil* to localtime*.
 | 
			
		||||
//   * Package changed from civil to toml.
 | 
			
		||||
//   * 'Local' prefix added to all structs.
 | 
			
		||||
//
 | 
			
		||||
// 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"
 | 
			
		||||
	"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.
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the date in RFC3339 full-date format.
 | 
			
		||||
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()
 | 
			
		||||
	return int(deltaUnix / 86400)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Before reports whether d1 occurs before d2.
 | 
			
		||||
func (d1 LocalDate) Before(d2 LocalDate) bool {
 | 
			
		||||
	if d1.Year != d2.Year {
 | 
			
		||||
		return d1.Year < d2.Year
 | 
			
		||||
	}
 | 
			
		||||
	if d1.Month != d2.Month {
 | 
			
		||||
		return d1.Month < d2.Month
 | 
			
		||||
	}
 | 
			
		||||
	return d1.Day < d2.Day
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// After reports whether d1 occurs after d2.
 | 
			
		||||
func (d1 LocalDate) After(d2 LocalDate) bool {
 | 
			
		||||
	return d2.Before(d1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalText implements the encoding.TextMarshaler interface.
 | 
			
		||||
// The output is the result of d.String().
 | 
			
		||||
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)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return LocalTime{}, err
 | 
			
		||||
	}
 | 
			
		||||
	return LocalTimeOf(t), 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
 | 
			
		||||
	}
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 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()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Before reports whether dt1 occurs before dt2.
 | 
			
		||||
func (dt1 LocalDateTime) Before(dt2 LocalDateTime) bool {
 | 
			
		||||
	return dt1.In(time.UTC).Before(dt2.In(time.UTC))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// After reports whether dt1 occurs after dt2.
 | 
			
		||||
func (dt1 LocalDateTime) After(dt2 LocalDateTime) bool {
 | 
			
		||||
	return dt2.Before(dt1)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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))
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1308
									
								
								vendor/github.com/pelletier/go-toml/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1308
									
								
								vendor/github.com/pelletier/go-toml/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										39
									
								
								vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,39 +0,0 @@
 | 
			
		||||
title = "TOML Marshal Testing"
 | 
			
		||||
 | 
			
		||||
[basic_lists]
 | 
			
		||||
  floats = [12.3,45.6,78.9]
 | 
			
		||||
  bools = [true,false,true]
 | 
			
		||||
  dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z]
 | 
			
		||||
  ints = [8001,8001,8002]
 | 
			
		||||
  uints = [5002,5003]
 | 
			
		||||
  strings = ["One","Two","Three"]
 | 
			
		||||
 | 
			
		||||
[[subdocptrs]]
 | 
			
		||||
  name = "Second"
 | 
			
		||||
 | 
			
		||||
[basic_map]
 | 
			
		||||
  one = "one"
 | 
			
		||||
  two = "two"
 | 
			
		||||
 | 
			
		||||
[subdoc]
 | 
			
		||||
 | 
			
		||||
  [subdoc.second]
 | 
			
		||||
    name = "Second"
 | 
			
		||||
 | 
			
		||||
  [subdoc.first]
 | 
			
		||||
    name = "First"
 | 
			
		||||
 | 
			
		||||
[basic]
 | 
			
		||||
  uint = 5001
 | 
			
		||||
  bool = true
 | 
			
		||||
  float = 123.4
 | 
			
		||||
  float64 = 123.456782132399
 | 
			
		||||
  int = 5000
 | 
			
		||||
  string = "Bite me"
 | 
			
		||||
  date = 1979-05-27T07:32:00Z
 | 
			
		||||
 | 
			
		||||
[[subdoclist]]
 | 
			
		||||
  name = "List.First"
 | 
			
		||||
 | 
			
		||||
[[subdoclist]]
 | 
			
		||||
  name = "List.Second"
 | 
			
		||||
							
								
								
									
										39
									
								
								vendor/github.com/pelletier/go-toml/marshal_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								vendor/github.com/pelletier/go-toml/marshal_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,39 +0,0 @@
 | 
			
		||||
title = "TOML Marshal Testing"
 | 
			
		||||
 | 
			
		||||
[basic]
 | 
			
		||||
  bool = true
 | 
			
		||||
  date = 1979-05-27T07:32:00Z
 | 
			
		||||
  float = 123.4
 | 
			
		||||
  float64 = 123.456782132399
 | 
			
		||||
  int = 5000
 | 
			
		||||
  string = "Bite me"
 | 
			
		||||
  uint = 5001
 | 
			
		||||
 | 
			
		||||
[basic_lists]
 | 
			
		||||
  bools = [true,false,true]
 | 
			
		||||
  dates = [1979-05-27T07:32:00Z,1980-05-27T07:32:00Z]
 | 
			
		||||
  floats = [12.3,45.6,78.9]
 | 
			
		||||
  ints = [8001,8001,8002]
 | 
			
		||||
  strings = ["One","Two","Three"]
 | 
			
		||||
  uints = [5002,5003]
 | 
			
		||||
 | 
			
		||||
[basic_map]
 | 
			
		||||
  one = "one"
 | 
			
		||||
  two = "two"
 | 
			
		||||
 | 
			
		||||
[subdoc]
 | 
			
		||||
 | 
			
		||||
  [subdoc.first]
 | 
			
		||||
    name = "First"
 | 
			
		||||
 | 
			
		||||
  [subdoc.second]
 | 
			
		||||
    name = "Second"
 | 
			
		||||
 | 
			
		||||
[[subdoclist]]
 | 
			
		||||
  name = "List.First"
 | 
			
		||||
 | 
			
		||||
[[subdoclist]]
 | 
			
		||||
  name = "List.Second"
 | 
			
		||||
 | 
			
		||||
[[subdocptrs]]
 | 
			
		||||
  name = "Second"
 | 
			
		||||
							
								
								
									
										507
									
								
								vendor/github.com/pelletier/go-toml/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										507
									
								
								vendor/github.com/pelletier/go-toml/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,507 +0,0 @@
 | 
			
		||||
// TOML Parser.
 | 
			
		||||
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type tomlParser struct {
 | 
			
		||||
	flowIdx       int
 | 
			
		||||
	flow          []token
 | 
			
		||||
	tree          *Tree
 | 
			
		||||
	currentTable  []string
 | 
			
		||||
	seenTableKeys []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type tomlParserStateFn func() tomlParserStateFn
 | 
			
		||||
 | 
			
		||||
// Formats and panics an error message based on a token
 | 
			
		||||
func (p *tomlParser) raiseError(tok *token, msg string, args ...interface{}) {
 | 
			
		||||
	panic(tok.Position.String() + ": " + fmt.Sprintf(msg, args...))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) run() {
 | 
			
		||||
	for state := p.parseStart; state != nil; {
 | 
			
		||||
		state = state()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) peek() *token {
 | 
			
		||||
	if p.flowIdx >= len(p.flow) {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return &p.flow[p.flowIdx]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) assume(typ tokenType) {
 | 
			
		||||
	tok := p.getToken()
 | 
			
		||||
	if tok == nil {
 | 
			
		||||
		p.raiseError(tok, "was expecting token %s, but token stream is empty", tok)
 | 
			
		||||
	}
 | 
			
		||||
	if tok.typ != typ {
 | 
			
		||||
		p.raiseError(tok, "was expecting token %s, but got %s instead", typ, tok)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) getToken() *token {
 | 
			
		||||
	tok := p.peek()
 | 
			
		||||
	if tok == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	p.flowIdx++
 | 
			
		||||
	return tok
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseStart() tomlParserStateFn {
 | 
			
		||||
	tok := p.peek()
 | 
			
		||||
 | 
			
		||||
	// end of stream, parsing is finished
 | 
			
		||||
	if tok == nil {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch tok.typ {
 | 
			
		||||
	case tokenDoubleLeftBracket:
 | 
			
		||||
		return p.parseGroupArray
 | 
			
		||||
	case tokenLeftBracket:
 | 
			
		||||
		return p.parseGroup
 | 
			
		||||
	case tokenKey:
 | 
			
		||||
		return p.parseAssign
 | 
			
		||||
	case tokenEOF:
 | 
			
		||||
		return nil
 | 
			
		||||
	case tokenError:
 | 
			
		||||
		p.raiseError(tok, "parsing error: %s", tok.String())
 | 
			
		||||
	default:
 | 
			
		||||
		p.raiseError(tok, "unexpected token %s", tok.typ)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseGroupArray() tomlParserStateFn {
 | 
			
		||||
	startToken := p.getToken() // discard the [[
 | 
			
		||||
	key := p.getToken()
 | 
			
		||||
	if key.typ != tokenKeyGroupArray {
 | 
			
		||||
		p.raiseError(key, "unexpected token %s, was expecting a table array key", key)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// get or create table array element at the indicated part in the path
 | 
			
		||||
	keys, err := parseKey(key.val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		p.raiseError(key, "invalid table array key: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	p.tree.createSubTree(keys[:len(keys)-1], startToken.Position) // create parent entries
 | 
			
		||||
	destTree := p.tree.GetPath(keys)
 | 
			
		||||
	var array []*Tree
 | 
			
		||||
	if destTree == nil {
 | 
			
		||||
		array = make([]*Tree, 0)
 | 
			
		||||
	} else if target, ok := destTree.([]*Tree); ok && target != nil {
 | 
			
		||||
		array = destTree.([]*Tree)
 | 
			
		||||
	} else {
 | 
			
		||||
		p.raiseError(key, "key %s is already assigned and not of type table array", key)
 | 
			
		||||
	}
 | 
			
		||||
	p.currentTable = keys
 | 
			
		||||
 | 
			
		||||
	// add a new tree to the end of the table array
 | 
			
		||||
	newTree := newTree()
 | 
			
		||||
	newTree.position = startToken.Position
 | 
			
		||||
	array = append(array, newTree)
 | 
			
		||||
	p.tree.SetPath(p.currentTable, array)
 | 
			
		||||
 | 
			
		||||
	// remove all keys that were children of this table array
 | 
			
		||||
	prefix := key.val + "."
 | 
			
		||||
	found := false
 | 
			
		||||
	for ii := 0; ii < len(p.seenTableKeys); {
 | 
			
		||||
		tableKey := p.seenTableKeys[ii]
 | 
			
		||||
		if strings.HasPrefix(tableKey, prefix) {
 | 
			
		||||
			p.seenTableKeys = append(p.seenTableKeys[:ii], p.seenTableKeys[ii+1:]...)
 | 
			
		||||
		} else {
 | 
			
		||||
			found = (tableKey == key.val)
 | 
			
		||||
			ii++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// keep this key name from use by other kinds of assignments
 | 
			
		||||
	if !found {
 | 
			
		||||
		p.seenTableKeys = append(p.seenTableKeys, key.val)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// move to next parser state
 | 
			
		||||
	p.assume(tokenDoubleRightBracket)
 | 
			
		||||
	return p.parseStart
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseGroup() tomlParserStateFn {
 | 
			
		||||
	startToken := p.getToken() // discard the [
 | 
			
		||||
	key := p.getToken()
 | 
			
		||||
	if key.typ != tokenKeyGroup {
 | 
			
		||||
		p.raiseError(key, "unexpected token %s, was expecting a table key", key)
 | 
			
		||||
	}
 | 
			
		||||
	for _, item := range p.seenTableKeys {
 | 
			
		||||
		if item == key.val {
 | 
			
		||||
			p.raiseError(key, "duplicated tables")
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	p.seenTableKeys = append(p.seenTableKeys, key.val)
 | 
			
		||||
	keys, err := parseKey(key.val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		p.raiseError(key, "invalid table array key: %s", err)
 | 
			
		||||
	}
 | 
			
		||||
	if err := p.tree.createSubTree(keys, startToken.Position); err != nil {
 | 
			
		||||
		p.raiseError(key, "%s", err)
 | 
			
		||||
	}
 | 
			
		||||
	destTree := p.tree.GetPath(keys)
 | 
			
		||||
	if target, ok := destTree.(*Tree); ok && target != nil && target.inline {
 | 
			
		||||
		p.raiseError(key, "could not re-define exist inline table or its sub-table : %s",
 | 
			
		||||
			strings.Join(keys, "."))
 | 
			
		||||
	}
 | 
			
		||||
	p.assume(tokenRightBracket)
 | 
			
		||||
	p.currentTable = keys
 | 
			
		||||
	return p.parseStart
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseAssign() tomlParserStateFn {
 | 
			
		||||
	key := p.getToken()
 | 
			
		||||
	p.assume(tokenEqual)
 | 
			
		||||
 | 
			
		||||
	parsedKey, err := parseKey(key.val)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		p.raiseError(key, "invalid key: %s", err.Error())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	value := p.parseRvalue()
 | 
			
		||||
	var tableKey []string
 | 
			
		||||
	if len(p.currentTable) > 0 {
 | 
			
		||||
		tableKey = p.currentTable
 | 
			
		||||
	} else {
 | 
			
		||||
		tableKey = []string{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	prefixKey := parsedKey[0 : len(parsedKey)-1]
 | 
			
		||||
	tableKey = append(tableKey, prefixKey...)
 | 
			
		||||
 | 
			
		||||
	// find the table to assign, looking out for arrays of tables
 | 
			
		||||
	var targetNode *Tree
 | 
			
		||||
	switch node := p.tree.GetPath(tableKey).(type) {
 | 
			
		||||
	case []*Tree:
 | 
			
		||||
		targetNode = node[len(node)-1]
 | 
			
		||||
	case *Tree:
 | 
			
		||||
		targetNode = node
 | 
			
		||||
	case nil:
 | 
			
		||||
		// create intermediate
 | 
			
		||||
		if err := p.tree.createSubTree(tableKey, key.Position); err != nil {
 | 
			
		||||
			p.raiseError(key, "could not create intermediate group: %s", err)
 | 
			
		||||
		}
 | 
			
		||||
		targetNode = p.tree.GetPath(tableKey).(*Tree)
 | 
			
		||||
	default:
 | 
			
		||||
		p.raiseError(key, "Unknown table type for path: %s",
 | 
			
		||||
			strings.Join(tableKey, "."))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if targetNode.inline {
 | 
			
		||||
		p.raiseError(key, "could not add key or sub-table to exist inline table or its sub-table : %s",
 | 
			
		||||
			strings.Join(tableKey, "."))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// assign value to the found table
 | 
			
		||||
	keyVal := parsedKey[len(parsedKey)-1]
 | 
			
		||||
	localKey := []string{keyVal}
 | 
			
		||||
	finalKey := append(tableKey, keyVal)
 | 
			
		||||
	if targetNode.GetPath(localKey) != nil {
 | 
			
		||||
		p.raiseError(key, "The following key was defined twice: %s",
 | 
			
		||||
			strings.Join(finalKey, "."))
 | 
			
		||||
	}
 | 
			
		||||
	var toInsert interface{}
 | 
			
		||||
 | 
			
		||||
	switch value.(type) {
 | 
			
		||||
	case *Tree, []*Tree:
 | 
			
		||||
		toInsert = value
 | 
			
		||||
	default:
 | 
			
		||||
		toInsert = &tomlValue{value: value, position: key.Position}
 | 
			
		||||
	}
 | 
			
		||||
	targetNode.values[keyVal] = toInsert
 | 
			
		||||
	return p.parseStart
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errInvalidUnderscore = errors.New("invalid use of _ in number")
 | 
			
		||||
 | 
			
		||||
func numberContainsInvalidUnderscore(value string) error {
 | 
			
		||||
	// For large numbers, you may use underscores between digits to enhance
 | 
			
		||||
	// readability. Each underscore must be surrounded by at least one digit on
 | 
			
		||||
	// each side.
 | 
			
		||||
 | 
			
		||||
	hasBefore := false
 | 
			
		||||
	for idx, r := range value {
 | 
			
		||||
		if r == '_' {
 | 
			
		||||
			if !hasBefore || idx+1 >= len(value) {
 | 
			
		||||
				// can't end with an underscore
 | 
			
		||||
				return errInvalidUnderscore
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		hasBefore = isDigit(r)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var errInvalidUnderscoreHex = errors.New("invalid use of _ in hex number")
 | 
			
		||||
 | 
			
		||||
func hexNumberContainsInvalidUnderscore(value string) error {
 | 
			
		||||
	hasBefore := false
 | 
			
		||||
	for idx, r := range value {
 | 
			
		||||
		if r == '_' {
 | 
			
		||||
			if !hasBefore || idx+1 >= len(value) {
 | 
			
		||||
				// can't end with an underscore
 | 
			
		||||
				return errInvalidUnderscoreHex
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		hasBefore = isHexDigit(r)
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func cleanupNumberToken(value string) string {
 | 
			
		||||
	cleanedVal := strings.Replace(value, "_", "", -1)
 | 
			
		||||
	return cleanedVal
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseRvalue() interface{} {
 | 
			
		||||
	tok := p.getToken()
 | 
			
		||||
	if tok == nil || tok.typ == tokenEOF {
 | 
			
		||||
		p.raiseError(tok, "expecting a value")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch tok.typ {
 | 
			
		||||
	case tokenString:
 | 
			
		||||
		return tok.val
 | 
			
		||||
	case tokenTrue:
 | 
			
		||||
		return true
 | 
			
		||||
	case tokenFalse:
 | 
			
		||||
		return false
 | 
			
		||||
	case tokenInf:
 | 
			
		||||
		if tok.val[0] == '-' {
 | 
			
		||||
			return math.Inf(-1)
 | 
			
		||||
		}
 | 
			
		||||
		return math.Inf(1)
 | 
			
		||||
	case tokenNan:
 | 
			
		||||
		return math.NaN()
 | 
			
		||||
	case tokenInteger:
 | 
			
		||||
		cleanedVal := cleanupNumberToken(tok.val)
 | 
			
		||||
		base := 10
 | 
			
		||||
		s := cleanedVal
 | 
			
		||||
		checkInvalidUnderscore := numberContainsInvalidUnderscore
 | 
			
		||||
		if len(cleanedVal) >= 3 && cleanedVal[0] == '0' {
 | 
			
		||||
			switch cleanedVal[1] {
 | 
			
		||||
			case 'x':
 | 
			
		||||
				checkInvalidUnderscore = hexNumberContainsInvalidUnderscore
 | 
			
		||||
				base = 16
 | 
			
		||||
			case 'o':
 | 
			
		||||
				base = 8
 | 
			
		||||
			case 'b':
 | 
			
		||||
				base = 2
 | 
			
		||||
			default:
 | 
			
		||||
				panic("invalid base") // the lexer should catch this first
 | 
			
		||||
			}
 | 
			
		||||
			s = cleanedVal[2:]
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		err := checkInvalidUnderscore(tok.val)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.raiseError(tok, "%s", err)
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		var val interface{}
 | 
			
		||||
		val, err = strconv.ParseInt(s, base, 64)
 | 
			
		||||
		if err == nil {
 | 
			
		||||
			return val
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if s[0] != '-' {
 | 
			
		||||
			if val, err = strconv.ParseUint(s, base, 64); err == nil {
 | 
			
		||||
				return val
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		p.raiseError(tok, "%s", err)
 | 
			
		||||
	case tokenFloat:
 | 
			
		||||
		err := numberContainsInvalidUnderscore(tok.val)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.raiseError(tok, "%s", err)
 | 
			
		||||
		}
 | 
			
		||||
		cleanedVal := cleanupNumberToken(tok.val)
 | 
			
		||||
		val, err := strconv.ParseFloat(cleanedVal, 64)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.raiseError(tok, "%s", err)
 | 
			
		||||
		}
 | 
			
		||||
		return val
 | 
			
		||||
	case tokenLocalTime:
 | 
			
		||||
		val, err := ParseLocalTime(tok.val)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.raiseError(tok, "%s", err)
 | 
			
		||||
		}
 | 
			
		||||
		return val
 | 
			
		||||
	case tokenLocalDate:
 | 
			
		||||
		// a local date may be followed by:
 | 
			
		||||
		// * nothing: this is a local date
 | 
			
		||||
		// * a local time: this is a local date-time
 | 
			
		||||
 | 
			
		||||
		next := p.peek()
 | 
			
		||||
		if next == nil || next.typ != tokenLocalTime {
 | 
			
		||||
			val, err := ParseLocalDate(tok.val)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				p.raiseError(tok, "%s", err)
 | 
			
		||||
			}
 | 
			
		||||
			return val
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		localDate := tok
 | 
			
		||||
		localTime := p.getToken()
 | 
			
		||||
 | 
			
		||||
		next = p.peek()
 | 
			
		||||
		if next == nil || next.typ != tokenTimeOffset {
 | 
			
		||||
			v := localDate.val + "T" + localTime.val
 | 
			
		||||
			val, err := ParseLocalDateTime(v)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				p.raiseError(tok, "%s", err)
 | 
			
		||||
			}
 | 
			
		||||
			return val
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		offset := p.getToken()
 | 
			
		||||
 | 
			
		||||
		layout := time.RFC3339Nano
 | 
			
		||||
		v := localDate.val + "T" + localTime.val + offset.val
 | 
			
		||||
		val, err := time.ParseInLocation(layout, v, time.UTC)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			p.raiseError(tok, "%s", err)
 | 
			
		||||
		}
 | 
			
		||||
		return val
 | 
			
		||||
	case tokenLeftBracket:
 | 
			
		||||
		return p.parseArray()
 | 
			
		||||
	case tokenLeftCurlyBrace:
 | 
			
		||||
		return p.parseInlineTable()
 | 
			
		||||
	case tokenEqual:
 | 
			
		||||
		p.raiseError(tok, "cannot have multiple equals for the same key")
 | 
			
		||||
	case tokenError:
 | 
			
		||||
		p.raiseError(tok, "%s", tok)
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Errorf("unhandled token: %v", tok))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tokenIsComma(t *token) bool {
 | 
			
		||||
	return t != nil && t.typ == tokenComma
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseInlineTable() *Tree {
 | 
			
		||||
	tree := newTree()
 | 
			
		||||
	var previous *token
 | 
			
		||||
Loop:
 | 
			
		||||
	for {
 | 
			
		||||
		follow := p.peek()
 | 
			
		||||
		if follow == nil || follow.typ == tokenEOF {
 | 
			
		||||
			p.raiseError(follow, "unterminated inline table")
 | 
			
		||||
		}
 | 
			
		||||
		switch follow.typ {
 | 
			
		||||
		case tokenRightCurlyBrace:
 | 
			
		||||
			p.getToken()
 | 
			
		||||
			break Loop
 | 
			
		||||
		case tokenKey, tokenInteger, tokenString:
 | 
			
		||||
			if !tokenIsComma(previous) && previous != nil {
 | 
			
		||||
				p.raiseError(follow, "comma expected between fields in inline table")
 | 
			
		||||
			}
 | 
			
		||||
			key := p.getToken()
 | 
			
		||||
			p.assume(tokenEqual)
 | 
			
		||||
 | 
			
		||||
			parsedKey, err := parseKey(key.val)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				p.raiseError(key, "invalid key: %s", err)
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			value := p.parseRvalue()
 | 
			
		||||
			tree.SetPath(parsedKey, value)
 | 
			
		||||
		case tokenComma:
 | 
			
		||||
			if tokenIsComma(previous) {
 | 
			
		||||
				p.raiseError(follow, "need field between two commas in inline table")
 | 
			
		||||
			}
 | 
			
		||||
			p.getToken()
 | 
			
		||||
		default:
 | 
			
		||||
			p.raiseError(follow, "unexpected token type in inline table: %s", follow.String())
 | 
			
		||||
		}
 | 
			
		||||
		previous = follow
 | 
			
		||||
	}
 | 
			
		||||
	if tokenIsComma(previous) {
 | 
			
		||||
		p.raiseError(previous, "trailing comma at the end of inline table")
 | 
			
		||||
	}
 | 
			
		||||
	tree.inline = true
 | 
			
		||||
	return tree
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (p *tomlParser) parseArray() interface{} {
 | 
			
		||||
	var array []interface{}
 | 
			
		||||
	arrayType := reflect.TypeOf(newTree())
 | 
			
		||||
	for {
 | 
			
		||||
		follow := p.peek()
 | 
			
		||||
		if follow == nil || follow.typ == tokenEOF {
 | 
			
		||||
			p.raiseError(follow, "unterminated array")
 | 
			
		||||
		}
 | 
			
		||||
		if follow.typ == tokenRightBracket {
 | 
			
		||||
			p.getToken()
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
		val := p.parseRvalue()
 | 
			
		||||
		if reflect.TypeOf(val) != arrayType {
 | 
			
		||||
			arrayType = nil
 | 
			
		||||
		}
 | 
			
		||||
		array = append(array, val)
 | 
			
		||||
		follow = p.peek()
 | 
			
		||||
		if follow == nil || follow.typ == tokenEOF {
 | 
			
		||||
			p.raiseError(follow, "unterminated array")
 | 
			
		||||
		}
 | 
			
		||||
		if follow.typ != tokenRightBracket && follow.typ != tokenComma {
 | 
			
		||||
			p.raiseError(follow, "missing comma")
 | 
			
		||||
		}
 | 
			
		||||
		if follow.typ == tokenComma {
 | 
			
		||||
			p.getToken()
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// if the array is a mixed-type array or its length is 0,
 | 
			
		||||
	// don't convert it to a table array
 | 
			
		||||
	if len(array) <= 0 {
 | 
			
		||||
		arrayType = nil
 | 
			
		||||
	}
 | 
			
		||||
	// An array of Trees is actually an array of inline
 | 
			
		||||
	// tables, which is a shorthand for a table array. If the
 | 
			
		||||
	// array was not converted from []interface{} to []*Tree,
 | 
			
		||||
	// the two notations would not be equivalent.
 | 
			
		||||
	if arrayType == reflect.TypeOf(newTree()) {
 | 
			
		||||
		tomlArray := make([]*Tree, len(array))
 | 
			
		||||
		for i, v := range array {
 | 
			
		||||
			tomlArray[i] = v.(*Tree)
 | 
			
		||||
		}
 | 
			
		||||
		return tomlArray
 | 
			
		||||
	}
 | 
			
		||||
	return array
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseToml(flow []token) *Tree {
 | 
			
		||||
	result := newTree()
 | 
			
		||||
	result.position = Position{1, 1}
 | 
			
		||||
	parser := &tomlParser{
 | 
			
		||||
		flowIdx:       0,
 | 
			
		||||
		flow:          flow,
 | 
			
		||||
		tree:          result,
 | 
			
		||||
		currentTable:  make([]string, 0),
 | 
			
		||||
		seenTableKeys: make([]string, 0),
 | 
			
		||||
	}
 | 
			
		||||
	parser.run()
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										29
									
								
								vendor/github.com/pelletier/go-toml/position.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/pelletier/go-toml/position.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,29 +0,0 @@
 | 
			
		||||
// Position support for go-toml
 | 
			
		||||
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Position of a document element within a TOML document.
 | 
			
		||||
//
 | 
			
		||||
// Line and Col are both 1-indexed positions for the element's line number and
 | 
			
		||||
// column number, respectively.  Values of zero or less will cause Invalid(),
 | 
			
		||||
// to return true.
 | 
			
		||||
type Position struct {
 | 
			
		||||
	Line int // line within the document
 | 
			
		||||
	Col  int // column within the line
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String representation of the position.
 | 
			
		||||
// Displays 1-indexed line and column numbers.
 | 
			
		||||
func (p Position) String() string {
 | 
			
		||||
	return fmt.Sprintf("(%d, %d)", p.Line, p.Col)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Invalid returns whether or not the position is valid (i.e. with negative or
 | 
			
		||||
// null values)
 | 
			
		||||
func (p Position) Invalid() bool {
 | 
			
		||||
	return p.Line <= 0 || p.Col <= 0
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										136
									
								
								vendor/github.com/pelletier/go-toml/token.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										136
									
								
								vendor/github.com/pelletier/go-toml/token.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,136 +0,0 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
// Define tokens
 | 
			
		||||
type tokenType int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	eof = -(iota + 1)
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	tokenError tokenType = iota
 | 
			
		||||
	tokenEOF
 | 
			
		||||
	tokenComment
 | 
			
		||||
	tokenKey
 | 
			
		||||
	tokenString
 | 
			
		||||
	tokenInteger
 | 
			
		||||
	tokenTrue
 | 
			
		||||
	tokenFalse
 | 
			
		||||
	tokenFloat
 | 
			
		||||
	tokenInf
 | 
			
		||||
	tokenNan
 | 
			
		||||
	tokenEqual
 | 
			
		||||
	tokenLeftBracket
 | 
			
		||||
	tokenRightBracket
 | 
			
		||||
	tokenLeftCurlyBrace
 | 
			
		||||
	tokenRightCurlyBrace
 | 
			
		||||
	tokenLeftParen
 | 
			
		||||
	tokenRightParen
 | 
			
		||||
	tokenDoubleLeftBracket
 | 
			
		||||
	tokenDoubleRightBracket
 | 
			
		||||
	tokenLocalDate
 | 
			
		||||
	tokenLocalTime
 | 
			
		||||
	tokenTimeOffset
 | 
			
		||||
	tokenKeyGroup
 | 
			
		||||
	tokenKeyGroupArray
 | 
			
		||||
	tokenComma
 | 
			
		||||
	tokenColon
 | 
			
		||||
	tokenDollar
 | 
			
		||||
	tokenStar
 | 
			
		||||
	tokenQuestion
 | 
			
		||||
	tokenDot
 | 
			
		||||
	tokenDotDot
 | 
			
		||||
	tokenEOL
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var tokenTypeNames = []string{
 | 
			
		||||
	"Error",
 | 
			
		||||
	"EOF",
 | 
			
		||||
	"Comment",
 | 
			
		||||
	"Key",
 | 
			
		||||
	"String",
 | 
			
		||||
	"Integer",
 | 
			
		||||
	"True",
 | 
			
		||||
	"False",
 | 
			
		||||
	"Float",
 | 
			
		||||
	"Inf",
 | 
			
		||||
	"NaN",
 | 
			
		||||
	"=",
 | 
			
		||||
	"[",
 | 
			
		||||
	"]",
 | 
			
		||||
	"{",
 | 
			
		||||
	"}",
 | 
			
		||||
	"(",
 | 
			
		||||
	")",
 | 
			
		||||
	"]]",
 | 
			
		||||
	"[[",
 | 
			
		||||
	"LocalDate",
 | 
			
		||||
	"LocalTime",
 | 
			
		||||
	"TimeOffset",
 | 
			
		||||
	"KeyGroup",
 | 
			
		||||
	"KeyGroupArray",
 | 
			
		||||
	",",
 | 
			
		||||
	":",
 | 
			
		||||
	"$",
 | 
			
		||||
	"*",
 | 
			
		||||
	"?",
 | 
			
		||||
	".",
 | 
			
		||||
	"..",
 | 
			
		||||
	"EOL",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type token struct {
 | 
			
		||||
	Position
 | 
			
		||||
	typ tokenType
 | 
			
		||||
	val string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tt tokenType) String() string {
 | 
			
		||||
	idx := int(tt)
 | 
			
		||||
	if idx < len(tokenTypeNames) {
 | 
			
		||||
		return tokenTypeNames[idx]
 | 
			
		||||
	}
 | 
			
		||||
	return "Unknown"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t token) String() string {
 | 
			
		||||
	switch t.typ {
 | 
			
		||||
	case tokenEOF:
 | 
			
		||||
		return "EOF"
 | 
			
		||||
	case tokenError:
 | 
			
		||||
		return t.val
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf("%q", t.val)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isSpace(r rune) bool {
 | 
			
		||||
	return r == ' ' || r == '\t'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isAlphanumeric(r rune) bool {
 | 
			
		||||
	return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isKeyChar(r rune) bool {
 | 
			
		||||
	// Keys start with the first character that isn't whitespace or [ and end
 | 
			
		||||
	// with the last non-whitespace character before the equals sign. Keys
 | 
			
		||||
	// cannot contain a # character."
 | 
			
		||||
	return !(r == '\r' || r == '\n' || r == eof || r == '=')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isKeyStartChar(r rune) bool {
 | 
			
		||||
	return !(isSpace(r) || r == '\r' || r == '\n' || r == eof || r == '[')
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isDigit(r rune) bool {
 | 
			
		||||
	return '0' <= r && r <= '9'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isHexDigit(r rune) bool {
 | 
			
		||||
	return isDigit(r) ||
 | 
			
		||||
		(r >= 'a' && r <= 'f') ||
 | 
			
		||||
		(r >= 'A' && r <= 'F')
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										533
									
								
								vendor/github.com/pelletier/go-toml/toml.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										533
									
								
								vendor/github.com/pelletier/go-toml/toml.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,533 +0,0 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"errors"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"io/ioutil"
 | 
			
		||||
	"os"
 | 
			
		||||
	"runtime"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type tomlValue struct {
 | 
			
		||||
	value     interface{} // string, int64, uint64, float64, bool, time.Time, [] of any of this list
 | 
			
		||||
	comment   string
 | 
			
		||||
	commented bool
 | 
			
		||||
	multiline bool
 | 
			
		||||
	literal   bool
 | 
			
		||||
	position  Position
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Tree is the result of the parsing of a TOML file.
 | 
			
		||||
type Tree struct {
 | 
			
		||||
	values    map[string]interface{} // string -> *tomlValue, *Tree, []*Tree
 | 
			
		||||
	comment   string
 | 
			
		||||
	commented bool
 | 
			
		||||
	inline    bool
 | 
			
		||||
	position  Position
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTree() *Tree {
 | 
			
		||||
	return newTreeWithPosition(Position{})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func newTreeWithPosition(pos Position) *Tree {
 | 
			
		||||
	return &Tree{
 | 
			
		||||
		values:   make(map[string]interface{}),
 | 
			
		||||
		position: pos,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// TreeFromMap initializes a new Tree object using the given map.
 | 
			
		||||
func TreeFromMap(m map[string]interface{}) (*Tree, error) {
 | 
			
		||||
	result, err := toTree(m)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return result.(*Tree), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Position returns the position of the tree.
 | 
			
		||||
func (t *Tree) Position() Position {
 | 
			
		||||
	return t.position
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Has returns a boolean indicating if the given key exists.
 | 
			
		||||
func (t *Tree) Has(key string) bool {
 | 
			
		||||
	if key == "" {
 | 
			
		||||
		return false
 | 
			
		||||
	}
 | 
			
		||||
	return t.HasPath(strings.Split(key, "."))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// HasPath returns true if the given path of keys exists, false otherwise.
 | 
			
		||||
func (t *Tree) HasPath(keys []string) bool {
 | 
			
		||||
	return t.GetPath(keys) != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Keys returns the keys of the toplevel tree (does not recurse).
 | 
			
		||||
func (t *Tree) Keys() []string {
 | 
			
		||||
	keys := make([]string, len(t.values))
 | 
			
		||||
	i := 0
 | 
			
		||||
	for k := range t.values {
 | 
			
		||||
		keys[i] = k
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
	return keys
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Get the value at key in the Tree.
 | 
			
		||||
// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings.
 | 
			
		||||
// If you need to retrieve non-bare keys, use GetPath.
 | 
			
		||||
// Returns nil if the path does not exist in the tree.
 | 
			
		||||
// If keys is of length zero, the current tree is returned.
 | 
			
		||||
func (t *Tree) Get(key string) interface{} {
 | 
			
		||||
	if key == "" {
 | 
			
		||||
		return t
 | 
			
		||||
	}
 | 
			
		||||
	return t.GetPath(strings.Split(key, "."))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPath returns the element in the tree indicated by 'keys'.
 | 
			
		||||
// If keys is of length zero, the current tree is returned.
 | 
			
		||||
func (t *Tree) GetPath(keys []string) interface{} {
 | 
			
		||||
	if len(keys) == 0 {
 | 
			
		||||
		return t
 | 
			
		||||
	}
 | 
			
		||||
	subtree := t
 | 
			
		||||
	for _, intermediateKey := range keys[:len(keys)-1] {
 | 
			
		||||
		value, exists := subtree.values[intermediateKey]
 | 
			
		||||
		if !exists {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		switch node := value.(type) {
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			subtree = node
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			// go to most recent element
 | 
			
		||||
			if len(node) == 0 {
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
			subtree = node[len(node)-1]
 | 
			
		||||
		default:
 | 
			
		||||
			return nil // cannot navigate through other node types
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// branch based on final node type
 | 
			
		||||
	switch node := subtree.values[keys[len(keys)-1]].(type) {
 | 
			
		||||
	case *tomlValue:
 | 
			
		||||
		return node.value
 | 
			
		||||
	default:
 | 
			
		||||
		return node
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetArray returns the value at key in the Tree.
 | 
			
		||||
// It returns []string, []int64, etc type if key has homogeneous lists
 | 
			
		||||
// Key is a dot-separated path (e.g. a.b.c) without single/double quoted strings.
 | 
			
		||||
// Returns nil if the path does not exist in the tree.
 | 
			
		||||
// If keys is of length zero, the current tree is returned.
 | 
			
		||||
func (t *Tree) GetArray(key string) interface{} {
 | 
			
		||||
	if key == "" {
 | 
			
		||||
		return t
 | 
			
		||||
	}
 | 
			
		||||
	return t.GetArrayPath(strings.Split(key, "."))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetArrayPath returns the element in the tree indicated by 'keys'.
 | 
			
		||||
// If keys is of length zero, the current tree is returned.
 | 
			
		||||
func (t *Tree) GetArrayPath(keys []string) interface{} {
 | 
			
		||||
	if len(keys) == 0 {
 | 
			
		||||
		return t
 | 
			
		||||
	}
 | 
			
		||||
	subtree := t
 | 
			
		||||
	for _, intermediateKey := range keys[:len(keys)-1] {
 | 
			
		||||
		value, exists := subtree.values[intermediateKey]
 | 
			
		||||
		if !exists {
 | 
			
		||||
			return nil
 | 
			
		||||
		}
 | 
			
		||||
		switch node := value.(type) {
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			subtree = node
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			// go to most recent element
 | 
			
		||||
			if len(node) == 0 {
 | 
			
		||||
				return nil
 | 
			
		||||
			}
 | 
			
		||||
			subtree = node[len(node)-1]
 | 
			
		||||
		default:
 | 
			
		||||
			return nil // cannot navigate through other node types
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// branch based on final node type
 | 
			
		||||
	switch node := subtree.values[keys[len(keys)-1]].(type) {
 | 
			
		||||
	case *tomlValue:
 | 
			
		||||
		switch n := node.value.(type) {
 | 
			
		||||
		case []interface{}:
 | 
			
		||||
			return getArray(n)
 | 
			
		||||
		default:
 | 
			
		||||
			return node.value
 | 
			
		||||
		}
 | 
			
		||||
	default:
 | 
			
		||||
		return node
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// if homogeneous array, then return slice type object over []interface{}
 | 
			
		||||
func getArray(n []interface{}) interface{} {
 | 
			
		||||
	var s []string
 | 
			
		||||
	var i64 []int64
 | 
			
		||||
	var f64 []float64
 | 
			
		||||
	var bl []bool
 | 
			
		||||
	for _, value := range n {
 | 
			
		||||
		switch v := value.(type) {
 | 
			
		||||
		case string:
 | 
			
		||||
			s = append(s, v)
 | 
			
		||||
		case int64:
 | 
			
		||||
			i64 = append(i64, v)
 | 
			
		||||
		case float64:
 | 
			
		||||
			f64 = append(f64, v)
 | 
			
		||||
		case bool:
 | 
			
		||||
			bl = append(bl, v)
 | 
			
		||||
		default:
 | 
			
		||||
			return n
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if len(s) == len(n) {
 | 
			
		||||
		return s
 | 
			
		||||
	} else if len(i64) == len(n) {
 | 
			
		||||
		return i64
 | 
			
		||||
	} else if len(f64) == len(n) {
 | 
			
		||||
		return f64
 | 
			
		||||
	} else if len(bl) == len(n) {
 | 
			
		||||
		return bl
 | 
			
		||||
	}
 | 
			
		||||
	return n
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPosition returns the position of the given key.
 | 
			
		||||
func (t *Tree) GetPosition(key string) Position {
 | 
			
		||||
	if key == "" {
 | 
			
		||||
		return t.position
 | 
			
		||||
	}
 | 
			
		||||
	return t.GetPositionPath(strings.Split(key, "."))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetPositionPath sets the position of element in the tree indicated by 'keys'.
 | 
			
		||||
// If keys is of length zero, the current tree position is set.
 | 
			
		||||
func (t *Tree) SetPositionPath(keys []string, pos Position) {
 | 
			
		||||
	if len(keys) == 0 {
 | 
			
		||||
		t.position = pos
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	subtree := t
 | 
			
		||||
	for _, intermediateKey := range keys[:len(keys)-1] {
 | 
			
		||||
		value, exists := subtree.values[intermediateKey]
 | 
			
		||||
		if !exists {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		switch node := value.(type) {
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			subtree = node
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			// go to most recent element
 | 
			
		||||
			if len(node) == 0 {
 | 
			
		||||
				return
 | 
			
		||||
			}
 | 
			
		||||
			subtree = node[len(node)-1]
 | 
			
		||||
		default:
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// branch based on final node type
 | 
			
		||||
	switch node := subtree.values[keys[len(keys)-1]].(type) {
 | 
			
		||||
	case *tomlValue:
 | 
			
		||||
		node.position = pos
 | 
			
		||||
		return
 | 
			
		||||
	case *Tree:
 | 
			
		||||
		node.position = pos
 | 
			
		||||
		return
 | 
			
		||||
	case []*Tree:
 | 
			
		||||
		// go to most recent element
 | 
			
		||||
		if len(node) == 0 {
 | 
			
		||||
			return
 | 
			
		||||
		}
 | 
			
		||||
		node[len(node)-1].position = pos
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetPositionPath returns the element in the tree indicated by 'keys'.
 | 
			
		||||
// If keys is of length zero, the current tree is returned.
 | 
			
		||||
func (t *Tree) GetPositionPath(keys []string) Position {
 | 
			
		||||
	if len(keys) == 0 {
 | 
			
		||||
		return t.position
 | 
			
		||||
	}
 | 
			
		||||
	subtree := t
 | 
			
		||||
	for _, intermediateKey := range keys[:len(keys)-1] {
 | 
			
		||||
		value, exists := subtree.values[intermediateKey]
 | 
			
		||||
		if !exists {
 | 
			
		||||
			return Position{0, 0}
 | 
			
		||||
		}
 | 
			
		||||
		switch node := value.(type) {
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			subtree = node
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			// go to most recent element
 | 
			
		||||
			if len(node) == 0 {
 | 
			
		||||
				return Position{0, 0}
 | 
			
		||||
			}
 | 
			
		||||
			subtree = node[len(node)-1]
 | 
			
		||||
		default:
 | 
			
		||||
			return Position{0, 0}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	// branch based on final node type
 | 
			
		||||
	switch node := subtree.values[keys[len(keys)-1]].(type) {
 | 
			
		||||
	case *tomlValue:
 | 
			
		||||
		return node.position
 | 
			
		||||
	case *Tree:
 | 
			
		||||
		return node.position
 | 
			
		||||
	case []*Tree:
 | 
			
		||||
		// go to most recent element
 | 
			
		||||
		if len(node) == 0 {
 | 
			
		||||
			return Position{0, 0}
 | 
			
		||||
		}
 | 
			
		||||
		return node[len(node)-1].position
 | 
			
		||||
	default:
 | 
			
		||||
		return Position{0, 0}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// GetDefault works like Get but with a default value
 | 
			
		||||
func (t *Tree) GetDefault(key string, def interface{}) interface{} {
 | 
			
		||||
	val := t.Get(key)
 | 
			
		||||
	if val == nil {
 | 
			
		||||
		return def
 | 
			
		||||
	}
 | 
			
		||||
	return val
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetOptions arguments are supplied to the SetWithOptions and SetPathWithOptions functions to modify marshalling behaviour.
 | 
			
		||||
// The default values within the struct are valid default options.
 | 
			
		||||
type SetOptions struct {
 | 
			
		||||
	Comment   string
 | 
			
		||||
	Commented bool
 | 
			
		||||
	Multiline bool
 | 
			
		||||
	Literal   bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetWithOptions is the same as Set, but allows you to provide formatting
 | 
			
		||||
// instructions to the key, that will be used by Marshal().
 | 
			
		||||
func (t *Tree) SetWithOptions(key string, opts SetOptions, value interface{}) {
 | 
			
		||||
	t.SetPathWithOptions(strings.Split(key, "."), opts, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetPathWithOptions is the same as SetPath, but allows you to provide
 | 
			
		||||
// formatting instructions to the key, that will be reused by Marshal().
 | 
			
		||||
func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interface{}) {
 | 
			
		||||
	subtree := t
 | 
			
		||||
	for i, intermediateKey := range keys[:len(keys)-1] {
 | 
			
		||||
		nextTree, exists := subtree.values[intermediateKey]
 | 
			
		||||
		if !exists {
 | 
			
		||||
			nextTree = newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
 | 
			
		||||
			subtree.values[intermediateKey] = nextTree // add new element here
 | 
			
		||||
		}
 | 
			
		||||
		switch node := nextTree.(type) {
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			subtree = node
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			// go to most recent element
 | 
			
		||||
			if len(node) == 0 {
 | 
			
		||||
				// create element if it does not exist
 | 
			
		||||
				node = append(node, newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col}))
 | 
			
		||||
				subtree.values[intermediateKey] = node
 | 
			
		||||
			}
 | 
			
		||||
			subtree = node[len(node)-1]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var toInsert interface{}
 | 
			
		||||
 | 
			
		||||
	switch v := value.(type) {
 | 
			
		||||
	case *Tree:
 | 
			
		||||
		v.comment = opts.Comment
 | 
			
		||||
		v.commented = opts.Commented
 | 
			
		||||
		toInsert = value
 | 
			
		||||
	case []*Tree:
 | 
			
		||||
		for i := range v {
 | 
			
		||||
			v[i].commented = opts.Commented
 | 
			
		||||
		}
 | 
			
		||||
		toInsert = value
 | 
			
		||||
	case *tomlValue:
 | 
			
		||||
		v.comment = opts.Comment
 | 
			
		||||
		v.commented = opts.Commented
 | 
			
		||||
		v.multiline = opts.Multiline
 | 
			
		||||
		v.literal = opts.Literal
 | 
			
		||||
		toInsert = v
 | 
			
		||||
	default:
 | 
			
		||||
		toInsert = &tomlValue{value: value,
 | 
			
		||||
			comment:   opts.Comment,
 | 
			
		||||
			commented: opts.Commented,
 | 
			
		||||
			multiline: opts.Multiline,
 | 
			
		||||
			literal:   opts.Literal,
 | 
			
		||||
			position:  Position{Line: subtree.position.Line + len(subtree.values) + 1, Col: subtree.position.Col}}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	subtree.values[keys[len(keys)-1]] = toInsert
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Set an element in the tree.
 | 
			
		||||
// Key is a dot-separated path (e.g. a.b.c).
 | 
			
		||||
// Creates all necessary intermediate trees, if needed.
 | 
			
		||||
func (t *Tree) Set(key string, value interface{}) {
 | 
			
		||||
	t.SetWithComment(key, "", false, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetWithComment is the same as Set, but allows you to provide comment
 | 
			
		||||
// information to the key, that will be reused by Marshal().
 | 
			
		||||
func (t *Tree) SetWithComment(key string, comment string, commented bool, value interface{}) {
 | 
			
		||||
	t.SetPathWithComment(strings.Split(key, "."), comment, commented, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetPath sets an element in the tree.
 | 
			
		||||
// Keys is an array of path elements (e.g. {"a","b","c"}).
 | 
			
		||||
// Creates all necessary intermediate trees, if needed.
 | 
			
		||||
func (t *Tree) SetPath(keys []string, value interface{}) {
 | 
			
		||||
	t.SetPathWithComment(keys, "", false, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// SetPathWithComment is the same as SetPath, but allows you to provide comment
 | 
			
		||||
// information to the key, that will be reused by Marshal().
 | 
			
		||||
func (t *Tree) SetPathWithComment(keys []string, comment string, commented bool, value interface{}) {
 | 
			
		||||
	t.SetPathWithOptions(keys, SetOptions{Comment: comment, Commented: commented}, value)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Delete removes a key from the tree.
 | 
			
		||||
// Key is a dot-separated path (e.g. a.b.c).
 | 
			
		||||
func (t *Tree) Delete(key string) error {
 | 
			
		||||
	keys, err := parseKey(key)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	return t.DeletePath(keys)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DeletePath removes a key from the tree.
 | 
			
		||||
// Keys is an array of path elements (e.g. {"a","b","c"}).
 | 
			
		||||
func (t *Tree) DeletePath(keys []string) error {
 | 
			
		||||
	keyLen := len(keys)
 | 
			
		||||
	if keyLen == 1 {
 | 
			
		||||
		delete(t.values, keys[0])
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	tree := t.GetPath(keys[:keyLen-1])
 | 
			
		||||
	item := keys[keyLen-1]
 | 
			
		||||
	switch node := tree.(type) {
 | 
			
		||||
	case *Tree:
 | 
			
		||||
		delete(node.values, item)
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	return errors.New("no such key to delete")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// createSubTree takes a tree and a key and create the necessary intermediate
 | 
			
		||||
// subtrees to create a subtree at that point. In-place.
 | 
			
		||||
//
 | 
			
		||||
// e.g. passing a.b.c will create (assuming tree is empty) tree[a], tree[a][b]
 | 
			
		||||
// and tree[a][b][c]
 | 
			
		||||
//
 | 
			
		||||
// Returns nil on success, error object on failure
 | 
			
		||||
func (t *Tree) createSubTree(keys []string, pos Position) error {
 | 
			
		||||
	subtree := t
 | 
			
		||||
	for i, intermediateKey := range keys {
 | 
			
		||||
		nextTree, exists := subtree.values[intermediateKey]
 | 
			
		||||
		if !exists {
 | 
			
		||||
			tree := newTreeWithPosition(Position{Line: t.position.Line + i, Col: t.position.Col})
 | 
			
		||||
			tree.position = pos
 | 
			
		||||
			tree.inline = subtree.inline
 | 
			
		||||
			subtree.values[intermediateKey] = tree
 | 
			
		||||
			nextTree = tree
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		switch node := nextTree.(type) {
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			subtree = node[len(node)-1]
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			subtree = node
 | 
			
		||||
		default:
 | 
			
		||||
			return fmt.Errorf("unknown type for path %s (%s): %T (%#v)",
 | 
			
		||||
				strings.Join(keys, "."), intermediateKey, nextTree, nextTree)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadBytes creates a Tree from a []byte.
 | 
			
		||||
func LoadBytes(b []byte) (tree *Tree, err error) {
 | 
			
		||||
	defer func() {
 | 
			
		||||
		if r := recover(); r != nil {
 | 
			
		||||
			if _, ok := r.(runtime.Error); ok {
 | 
			
		||||
				panic(r)
 | 
			
		||||
			}
 | 
			
		||||
			err = fmt.Errorf("%s", r)
 | 
			
		||||
		}
 | 
			
		||||
	}()
 | 
			
		||||
 | 
			
		||||
	if len(b) >= 4 && (hasUTF32BigEndianBOM4(b) || hasUTF32LittleEndianBOM4(b)) {
 | 
			
		||||
		b = b[4:]
 | 
			
		||||
	} else if len(b) >= 3 && hasUTF8BOM3(b) {
 | 
			
		||||
		b = b[3:]
 | 
			
		||||
	} else if len(b) >= 2 && (hasUTF16BigEndianBOM2(b) || hasUTF16LittleEndianBOM2(b)) {
 | 
			
		||||
		b = b[2:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	tree = parseToml(lexToml(b))
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasUTF16BigEndianBOM2(b []byte) bool {
 | 
			
		||||
	return b[0] == 0xFE && b[1] == 0xFF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasUTF16LittleEndianBOM2(b []byte) bool {
 | 
			
		||||
	return b[0] == 0xFF && b[1] == 0xFE
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasUTF8BOM3(b []byte) bool {
 | 
			
		||||
	return b[0] == 0xEF && b[1] == 0xBB && b[2] == 0xBF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasUTF32BigEndianBOM4(b []byte) bool {
 | 
			
		||||
	return b[0] == 0x00 && b[1] == 0x00 && b[2] == 0xFE && b[3] == 0xFF
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func hasUTF32LittleEndianBOM4(b []byte) bool {
 | 
			
		||||
	return b[0] == 0xFF && b[1] == 0xFE && b[2] == 0x00 && b[3] == 0x00
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadReader creates a Tree from any io.Reader.
 | 
			
		||||
func LoadReader(reader io.Reader) (tree *Tree, err error) {
 | 
			
		||||
	inputBytes, err := ioutil.ReadAll(reader)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
	tree, err = LoadBytes(inputBytes)
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Load creates a Tree from a string.
 | 
			
		||||
func Load(content string) (tree *Tree, err error) {
 | 
			
		||||
	return LoadBytes([]byte(content))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LoadFile creates a Tree from a file.
 | 
			
		||||
func LoadFile(path string) (tree *Tree, err error) {
 | 
			
		||||
	file, err := os.Open(path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	defer file.Close()
 | 
			
		||||
	return LoadReader(file)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								vendor/github.com/pelletier/go-toml/tomlpub.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/pelletier/go-toml/tomlpub.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,71 +0,0 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
// PubTOMLValue wrapping tomlValue in order to access all properties from outside.
 | 
			
		||||
type PubTOMLValue = tomlValue
 | 
			
		||||
 | 
			
		||||
func (ptv *PubTOMLValue) Value() interface{} {
 | 
			
		||||
	return ptv.value
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) Comment() string {
 | 
			
		||||
	return ptv.comment
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) Commented() bool {
 | 
			
		||||
	return ptv.commented
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) Multiline() bool {
 | 
			
		||||
	return ptv.multiline
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) Position() Position {
 | 
			
		||||
	return ptv.position
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ptv *PubTOMLValue) SetValue(v interface{}) {
 | 
			
		||||
	ptv.value = v
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) SetComment(s string) {
 | 
			
		||||
	ptv.comment = s
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) SetCommented(c bool) {
 | 
			
		||||
	ptv.commented = c
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) SetMultiline(m bool) {
 | 
			
		||||
	ptv.multiline = m
 | 
			
		||||
}
 | 
			
		||||
func (ptv *PubTOMLValue) SetPosition(p Position) {
 | 
			
		||||
	ptv.position = p
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// PubTree wrapping Tree in order to access all properties from outside.
 | 
			
		||||
type PubTree = Tree
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) Values() map[string]interface{} {
 | 
			
		||||
	return pt.values
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) Comment() string {
 | 
			
		||||
	return pt.comment
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) Commented() bool {
 | 
			
		||||
	return pt.commented
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) Inline() bool {
 | 
			
		||||
	return pt.inline
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) SetValues(v map[string]interface{}) {
 | 
			
		||||
	pt.values = v
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) SetComment(c string) {
 | 
			
		||||
	pt.comment = c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) SetCommented(c bool) {
 | 
			
		||||
	pt.commented = c
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (pt *PubTree) SetInline(i bool) {
 | 
			
		||||
	pt.inline = i
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										155
									
								
								vendor/github.com/pelletier/go-toml/tomltree_create.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										155
									
								
								vendor/github.com/pelletier/go-toml/tomltree_create.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,155 +0,0 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var kindToType = [reflect.String + 1]reflect.Type{
 | 
			
		||||
	reflect.Bool:    reflect.TypeOf(true),
 | 
			
		||||
	reflect.String:  reflect.TypeOf(""),
 | 
			
		||||
	reflect.Float32: reflect.TypeOf(float64(1)),
 | 
			
		||||
	reflect.Float64: reflect.TypeOf(float64(1)),
 | 
			
		||||
	reflect.Int:     reflect.TypeOf(int64(1)),
 | 
			
		||||
	reflect.Int8:    reflect.TypeOf(int64(1)),
 | 
			
		||||
	reflect.Int16:   reflect.TypeOf(int64(1)),
 | 
			
		||||
	reflect.Int32:   reflect.TypeOf(int64(1)),
 | 
			
		||||
	reflect.Int64:   reflect.TypeOf(int64(1)),
 | 
			
		||||
	reflect.Uint:    reflect.TypeOf(uint64(1)),
 | 
			
		||||
	reflect.Uint8:   reflect.TypeOf(uint64(1)),
 | 
			
		||||
	reflect.Uint16:  reflect.TypeOf(uint64(1)),
 | 
			
		||||
	reflect.Uint32:  reflect.TypeOf(uint64(1)),
 | 
			
		||||
	reflect.Uint64:  reflect.TypeOf(uint64(1)),
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// typeFor returns a reflect.Type for a reflect.Kind, or nil if none is found.
 | 
			
		||||
// supported values:
 | 
			
		||||
// string, bool, int64, uint64, float64, time.Time, int, int8, int16, int32, uint, uint8, uint16, uint32, float32
 | 
			
		||||
func typeFor(k reflect.Kind) reflect.Type {
 | 
			
		||||
	if k > 0 && int(k) < len(kindToType) {
 | 
			
		||||
		return kindToType[k]
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func simpleValueCoercion(object interface{}) (interface{}, error) {
 | 
			
		||||
	switch original := object.(type) {
 | 
			
		||||
	case string, bool, int64, uint64, float64, time.Time:
 | 
			
		||||
		return original, nil
 | 
			
		||||
	case int:
 | 
			
		||||
		return int64(original), nil
 | 
			
		||||
	case int8:
 | 
			
		||||
		return int64(original), nil
 | 
			
		||||
	case int16:
 | 
			
		||||
		return int64(original), nil
 | 
			
		||||
	case int32:
 | 
			
		||||
		return int64(original), nil
 | 
			
		||||
	case uint:
 | 
			
		||||
		return uint64(original), nil
 | 
			
		||||
	case uint8:
 | 
			
		||||
		return uint64(original), nil
 | 
			
		||||
	case uint16:
 | 
			
		||||
		return uint64(original), nil
 | 
			
		||||
	case uint32:
 | 
			
		||||
		return uint64(original), nil
 | 
			
		||||
	case float32:
 | 
			
		||||
		return float64(original), nil
 | 
			
		||||
	case fmt.Stringer:
 | 
			
		||||
		return original.String(), nil
 | 
			
		||||
	case []interface{}:
 | 
			
		||||
		value := reflect.ValueOf(original)
 | 
			
		||||
		length := value.Len()
 | 
			
		||||
		arrayValue := reflect.MakeSlice(value.Type(), 0, length)
 | 
			
		||||
		for i := 0; i < length; i++ {
 | 
			
		||||
			val := value.Index(i).Interface()
 | 
			
		||||
			simpleValue, err := simpleValueCoercion(val)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
 | 
			
		||||
		}
 | 
			
		||||
		return arrayValue.Interface(), nil
 | 
			
		||||
	default:
 | 
			
		||||
		return nil, fmt.Errorf("cannot convert type %T to Tree", object)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sliceToTree(object interface{}) (interface{}, error) {
 | 
			
		||||
	// arrays are a bit tricky, since they can represent either a
 | 
			
		||||
	// collection of simple values, which is represented by one
 | 
			
		||||
	// *tomlValue, or an array of tables, which is represented by an
 | 
			
		||||
	// array of *Tree.
 | 
			
		||||
 | 
			
		||||
	// holding the assumption that this function is called from toTree only when value.Kind() is Array or Slice
 | 
			
		||||
	value := reflect.ValueOf(object)
 | 
			
		||||
	insideType := value.Type().Elem()
 | 
			
		||||
	length := value.Len()
 | 
			
		||||
	if length > 0 {
 | 
			
		||||
		insideType = reflect.ValueOf(value.Index(0).Interface()).Type()
 | 
			
		||||
	}
 | 
			
		||||
	if insideType.Kind() == reflect.Map {
 | 
			
		||||
		// this is considered as an array of tables
 | 
			
		||||
		tablesArray := make([]*Tree, 0, length)
 | 
			
		||||
		for i := 0; i < length; i++ {
 | 
			
		||||
			table := value.Index(i)
 | 
			
		||||
			tree, err := toTree(table.Interface())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			tablesArray = append(tablesArray, tree.(*Tree))
 | 
			
		||||
		}
 | 
			
		||||
		return tablesArray, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sliceType := typeFor(insideType.Kind())
 | 
			
		||||
	if sliceType == nil {
 | 
			
		||||
		sliceType = insideType
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	arrayValue := reflect.MakeSlice(reflect.SliceOf(sliceType), 0, length)
 | 
			
		||||
 | 
			
		||||
	for i := 0; i < length; i++ {
 | 
			
		||||
		val := value.Index(i).Interface()
 | 
			
		||||
		simpleValue, err := simpleValueCoercion(val)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
		arrayValue = reflect.Append(arrayValue, reflect.ValueOf(simpleValue))
 | 
			
		||||
	}
 | 
			
		||||
	return &tomlValue{value: arrayValue.Interface(), position: Position{}}, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func toTree(object interface{}) (interface{}, error) {
 | 
			
		||||
	value := reflect.ValueOf(object)
 | 
			
		||||
 | 
			
		||||
	if value.Kind() == reflect.Map {
 | 
			
		||||
		values := map[string]interface{}{}
 | 
			
		||||
		keys := value.MapKeys()
 | 
			
		||||
		for _, key := range keys {
 | 
			
		||||
			if key.Kind() != reflect.String {
 | 
			
		||||
				if _, ok := key.Interface().(string); !ok {
 | 
			
		||||
					return nil, fmt.Errorf("map key needs to be a string, not %T (%v)", key.Interface(), key.Kind())
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			v := value.MapIndex(key)
 | 
			
		||||
			newValue, err := toTree(v.Interface())
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return nil, err
 | 
			
		||||
			}
 | 
			
		||||
			values[key.String()] = newValue
 | 
			
		||||
		}
 | 
			
		||||
		return &Tree{values: values, position: Position{}}, nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if value.Kind() == reflect.Array || value.Kind() == reflect.Slice {
 | 
			
		||||
		return sliceToTree(object)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	simpleValue, err := simpleValueCoercion(object)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
	return &tomlValue{value: simpleValue, position: Position{}}, nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										552
									
								
								vendor/github.com/pelletier/go-toml/tomltree_write.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										552
									
								
								vendor/github.com/pelletier/go-toml/tomltree_write.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,552 +0,0 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"math"
 | 
			
		||||
	"math/big"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"sort"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type valueComplexity int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	valueSimple valueComplexity = iota + 1
 | 
			
		||||
	valueComplex
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type sortNode struct {
 | 
			
		||||
	key        string
 | 
			
		||||
	complexity valueComplexity
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encodes a string to a TOML-compliant multi-line string value
 | 
			
		||||
// This function is a clone of the existing encodeTomlString function, except that whitespace characters
 | 
			
		||||
// are preserved. Quotation marks and backslashes are also not escaped.
 | 
			
		||||
func encodeMultilineTomlString(value string, commented string) string {
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
	adjacentQuoteCount := 0
 | 
			
		||||
 | 
			
		||||
	b.WriteString(commented)
 | 
			
		||||
	for i, rr := range value {
 | 
			
		||||
		if rr != '"' {
 | 
			
		||||
			adjacentQuoteCount = 0
 | 
			
		||||
		} else {
 | 
			
		||||
			adjacentQuoteCount++
 | 
			
		||||
		}
 | 
			
		||||
		switch rr {
 | 
			
		||||
		case '\b':
 | 
			
		||||
			b.WriteString(`\b`)
 | 
			
		||||
		case '\t':
 | 
			
		||||
			b.WriteString("\t")
 | 
			
		||||
		case '\n':
 | 
			
		||||
			b.WriteString("\n" + commented)
 | 
			
		||||
		case '\f':
 | 
			
		||||
			b.WriteString(`\f`)
 | 
			
		||||
		case '\r':
 | 
			
		||||
			b.WriteString("\r")
 | 
			
		||||
		case '"':
 | 
			
		||||
			if adjacentQuoteCount >= 3 || i == len(value)-1 {
 | 
			
		||||
				adjacentQuoteCount = 0
 | 
			
		||||
				b.WriteString(`\"`)
 | 
			
		||||
			} else {
 | 
			
		||||
				b.WriteString(`"`)
 | 
			
		||||
			}
 | 
			
		||||
		case '\\':
 | 
			
		||||
			b.WriteString(`\`)
 | 
			
		||||
		default:
 | 
			
		||||
			intRr := uint16(rr)
 | 
			
		||||
			if intRr < 0x001F {
 | 
			
		||||
				b.WriteString(fmt.Sprintf("\\u%0.4X", intRr))
 | 
			
		||||
			} else {
 | 
			
		||||
				b.WriteRune(rr)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return b.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Encodes a string to a TOML-compliant string value
 | 
			
		||||
func encodeTomlString(value string) string {
 | 
			
		||||
	var b bytes.Buffer
 | 
			
		||||
 | 
			
		||||
	for _, rr := range value {
 | 
			
		||||
		switch rr {
 | 
			
		||||
		case '\b':
 | 
			
		||||
			b.WriteString(`\b`)
 | 
			
		||||
		case '\t':
 | 
			
		||||
			b.WriteString(`\t`)
 | 
			
		||||
		case '\n':
 | 
			
		||||
			b.WriteString(`\n`)
 | 
			
		||||
		case '\f':
 | 
			
		||||
			b.WriteString(`\f`)
 | 
			
		||||
		case '\r':
 | 
			
		||||
			b.WriteString(`\r`)
 | 
			
		||||
		case '"':
 | 
			
		||||
			b.WriteString(`\"`)
 | 
			
		||||
		case '\\':
 | 
			
		||||
			b.WriteString(`\\`)
 | 
			
		||||
		default:
 | 
			
		||||
			intRr := uint16(rr)
 | 
			
		||||
			if intRr < 0x001F {
 | 
			
		||||
				b.WriteString(fmt.Sprintf("\\u%0.4X", intRr))
 | 
			
		||||
			} else {
 | 
			
		||||
				b.WriteRune(rr)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return b.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tomlTreeStringRepresentation(t *Tree, ord MarshalOrder) (string, error) {
 | 
			
		||||
	var orderedVals []sortNode
 | 
			
		||||
	switch ord {
 | 
			
		||||
	case OrderPreserve:
 | 
			
		||||
		orderedVals = sortByLines(t)
 | 
			
		||||
	default:
 | 
			
		||||
		orderedVals = sortAlphabetical(t)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var values []string
 | 
			
		||||
	for _, node := range orderedVals {
 | 
			
		||||
		k := node.key
 | 
			
		||||
		v := t.values[k]
 | 
			
		||||
 | 
			
		||||
		repr, err := tomlValueStringRepresentation(v, "", "", ord, false)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
		values = append(values, quoteKeyIfNeeded(k)+" = "+repr)
 | 
			
		||||
	}
 | 
			
		||||
	return "{ " + strings.Join(values, ", ") + " }", nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tomlValueStringRepresentation(v interface{}, commented string, indent string, ord MarshalOrder, arraysOneElementPerLine bool) (string, error) {
 | 
			
		||||
	// this interface check is added to dereference the change made in the writeTo function.
 | 
			
		||||
	// That change was made to allow this function to see formatting options.
 | 
			
		||||
	tv, ok := v.(*tomlValue)
 | 
			
		||||
	if ok {
 | 
			
		||||
		v = tv.value
 | 
			
		||||
	} else {
 | 
			
		||||
		tv = &tomlValue{}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	switch value := v.(type) {
 | 
			
		||||
	case uint64:
 | 
			
		||||
		return strconv.FormatUint(value, 10), nil
 | 
			
		||||
	case int64:
 | 
			
		||||
		return strconv.FormatInt(value, 10), nil
 | 
			
		||||
	case float64:
 | 
			
		||||
		// Default bit length is full 64
 | 
			
		||||
		bits := 64
 | 
			
		||||
		// Float panics if nan is used
 | 
			
		||||
		if !math.IsNaN(value) {
 | 
			
		||||
			// if 32 bit accuracy is enough to exactly show, use 32
 | 
			
		||||
			_, acc := big.NewFloat(value).Float32()
 | 
			
		||||
			if acc == big.Exact {
 | 
			
		||||
				bits = 32
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		if math.Trunc(value) == value {
 | 
			
		||||
			return strings.ToLower(strconv.FormatFloat(value, 'f', 1, bits)), nil
 | 
			
		||||
		}
 | 
			
		||||
		return strings.ToLower(strconv.FormatFloat(value, 'f', -1, bits)), nil
 | 
			
		||||
	case string:
 | 
			
		||||
		if tv.multiline {
 | 
			
		||||
			if tv.literal {
 | 
			
		||||
				b := strings.Builder{}
 | 
			
		||||
				b.WriteString("'''\n")
 | 
			
		||||
				b.Write([]byte(value))
 | 
			
		||||
				b.WriteString("\n'''")
 | 
			
		||||
				return b.String(), nil
 | 
			
		||||
			} else {
 | 
			
		||||
				return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		return "\"" + encodeTomlString(value) + "\"", nil
 | 
			
		||||
	case []byte:
 | 
			
		||||
		b, _ := v.([]byte)
 | 
			
		||||
		return string(b), nil
 | 
			
		||||
	case bool:
 | 
			
		||||
		if value {
 | 
			
		||||
			return "true", nil
 | 
			
		||||
		}
 | 
			
		||||
		return "false", nil
 | 
			
		||||
	case time.Time:
 | 
			
		||||
		return value.Format(time.RFC3339), nil
 | 
			
		||||
	case LocalDate:
 | 
			
		||||
		return value.String(), nil
 | 
			
		||||
	case LocalDateTime:
 | 
			
		||||
		return value.String(), nil
 | 
			
		||||
	case LocalTime:
 | 
			
		||||
		return value.String(), nil
 | 
			
		||||
	case *Tree:
 | 
			
		||||
		return tomlTreeStringRepresentation(value, ord)
 | 
			
		||||
	case nil:
 | 
			
		||||
		return "", nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv := reflect.ValueOf(v)
 | 
			
		||||
 | 
			
		||||
	if rv.Kind() == reflect.Slice {
 | 
			
		||||
		var values []string
 | 
			
		||||
		for i := 0; i < rv.Len(); i++ {
 | 
			
		||||
			item := rv.Index(i).Interface()
 | 
			
		||||
			itemRepr, err := tomlValueStringRepresentation(item, commented, indent, ord, arraysOneElementPerLine)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return "", err
 | 
			
		||||
			}
 | 
			
		||||
			values = append(values, itemRepr)
 | 
			
		||||
		}
 | 
			
		||||
		if arraysOneElementPerLine && len(values) > 1 {
 | 
			
		||||
			stringBuffer := bytes.Buffer{}
 | 
			
		||||
			valueIndent := indent + `  ` // TODO: move that to a shared encoder state
 | 
			
		||||
 | 
			
		||||
			stringBuffer.WriteString("[\n")
 | 
			
		||||
 | 
			
		||||
			for _, value := range values {
 | 
			
		||||
				stringBuffer.WriteString(valueIndent)
 | 
			
		||||
				stringBuffer.WriteString(commented + value)
 | 
			
		||||
				stringBuffer.WriteString(`,`)
 | 
			
		||||
				stringBuffer.WriteString("\n")
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			stringBuffer.WriteString(indent + commented + "]")
 | 
			
		||||
 | 
			
		||||
			return stringBuffer.String(), nil
 | 
			
		||||
		}
 | 
			
		||||
		return "[" + strings.Join(values, ", ") + "]", nil
 | 
			
		||||
	}
 | 
			
		||||
	return "", fmt.Errorf("unsupported value type %T: %v", v, v)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func getTreeArrayLine(trees []*Tree) (line int) {
 | 
			
		||||
	// Prevent returning 0 for empty trees
 | 
			
		||||
	line = int(^uint(0) >> 1)
 | 
			
		||||
	// get lowest line number >= 0
 | 
			
		||||
	for _, tv := range trees {
 | 
			
		||||
		if tv.position.Line < line || line == 0 {
 | 
			
		||||
			line = tv.position.Line
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sortByLines(t *Tree) (vals []sortNode) {
 | 
			
		||||
	var (
 | 
			
		||||
		line  int
 | 
			
		||||
		lines []int
 | 
			
		||||
		tv    *Tree
 | 
			
		||||
		tom   *tomlValue
 | 
			
		||||
		node  sortNode
 | 
			
		||||
	)
 | 
			
		||||
	vals = make([]sortNode, 0)
 | 
			
		||||
	m := make(map[int]sortNode)
 | 
			
		||||
 | 
			
		||||
	for k := range t.values {
 | 
			
		||||
		v := t.values[k]
 | 
			
		||||
		switch v.(type) {
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			tv = v.(*Tree)
 | 
			
		||||
			line = tv.position.Line
 | 
			
		||||
			node = sortNode{key: k, complexity: valueComplex}
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			line = getTreeArrayLine(v.([]*Tree))
 | 
			
		||||
			node = sortNode{key: k, complexity: valueComplex}
 | 
			
		||||
		default:
 | 
			
		||||
			tom = v.(*tomlValue)
 | 
			
		||||
			line = tom.position.Line
 | 
			
		||||
			node = sortNode{key: k, complexity: valueSimple}
 | 
			
		||||
		}
 | 
			
		||||
		lines = append(lines, line)
 | 
			
		||||
		vals = append(vals, node)
 | 
			
		||||
		m[line] = node
 | 
			
		||||
	}
 | 
			
		||||
	sort.Ints(lines)
 | 
			
		||||
 | 
			
		||||
	for i, line := range lines {
 | 
			
		||||
		vals[i] = m[line]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vals
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func sortAlphabetical(t *Tree) (vals []sortNode) {
 | 
			
		||||
	var (
 | 
			
		||||
		node     sortNode
 | 
			
		||||
		simpVals []string
 | 
			
		||||
		compVals []string
 | 
			
		||||
	)
 | 
			
		||||
	vals = make([]sortNode, 0)
 | 
			
		||||
	m := make(map[string]sortNode)
 | 
			
		||||
 | 
			
		||||
	for k := range t.values {
 | 
			
		||||
		v := t.values[k]
 | 
			
		||||
		switch v.(type) {
 | 
			
		||||
		case *Tree, []*Tree:
 | 
			
		||||
			node = sortNode{key: k, complexity: valueComplex}
 | 
			
		||||
			compVals = append(compVals, node.key)
 | 
			
		||||
		default:
 | 
			
		||||
			node = sortNode{key: k, complexity: valueSimple}
 | 
			
		||||
			simpVals = append(simpVals, node.key)
 | 
			
		||||
		}
 | 
			
		||||
		vals = append(vals, node)
 | 
			
		||||
		m[node.key] = node
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Simples first to match previous implementation
 | 
			
		||||
	sort.Strings(simpVals)
 | 
			
		||||
	i := 0
 | 
			
		||||
	for _, key := range simpVals {
 | 
			
		||||
		vals[i] = m[key]
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	sort.Strings(compVals)
 | 
			
		||||
	for _, key := range compVals {
 | 
			
		||||
		vals[i] = m[key]
 | 
			
		||||
		i++
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return vals
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Tree) writeTo(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool) (int64, error) {
 | 
			
		||||
	return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical, "  ", false, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord MarshalOrder, indentString string, compactComments, parentCommented bool) (int64, error) {
 | 
			
		||||
	var orderedVals []sortNode
 | 
			
		||||
 | 
			
		||||
	switch ord {
 | 
			
		||||
	case OrderPreserve:
 | 
			
		||||
		orderedVals = sortByLines(t)
 | 
			
		||||
	default:
 | 
			
		||||
		orderedVals = sortAlphabetical(t)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, node := range orderedVals {
 | 
			
		||||
		switch node.complexity {
 | 
			
		||||
		case valueComplex:
 | 
			
		||||
			k := node.key
 | 
			
		||||
			v := t.values[k]
 | 
			
		||||
 | 
			
		||||
			combinedKey := quoteKeyIfNeeded(k)
 | 
			
		||||
			if keyspace != "" {
 | 
			
		||||
				combinedKey = keyspace + "." + combinedKey
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			switch node := v.(type) {
 | 
			
		||||
			// node has to be of those two types given how keys are sorted above
 | 
			
		||||
			case *Tree:
 | 
			
		||||
				tv, ok := t.values[k].(*Tree)
 | 
			
		||||
				if !ok {
 | 
			
		||||
					return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
 | 
			
		||||
				}
 | 
			
		||||
				if tv.comment != "" {
 | 
			
		||||
					comment := strings.Replace(tv.comment, "\n", "\n"+indent+"#", -1)
 | 
			
		||||
					start := "# "
 | 
			
		||||
					if strings.HasPrefix(comment, "#") {
 | 
			
		||||
						start = ""
 | 
			
		||||
					}
 | 
			
		||||
					writtenBytesCountComment, errc := writeStrings(w, "\n", indent, start, comment)
 | 
			
		||||
					bytesCount += int64(writtenBytesCountComment)
 | 
			
		||||
					if errc != nil {
 | 
			
		||||
						return bytesCount, errc
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				var commented string
 | 
			
		||||
				if parentCommented || t.commented || tv.commented {
 | 
			
		||||
					commented = "# "
 | 
			
		||||
				}
 | 
			
		||||
				writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[", combinedKey, "]\n")
 | 
			
		||||
				bytesCount += int64(writtenBytesCount)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return bytesCount, err
 | 
			
		||||
				}
 | 
			
		||||
				bytesCount, err = node.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, compactComments, parentCommented || t.commented || tv.commented)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return bytesCount, err
 | 
			
		||||
				}
 | 
			
		||||
			case []*Tree:
 | 
			
		||||
				for _, subTree := range node {
 | 
			
		||||
					var commented string
 | 
			
		||||
					if parentCommented || t.commented || subTree.commented {
 | 
			
		||||
						commented = "# "
 | 
			
		||||
					}
 | 
			
		||||
					writtenBytesCount, err := writeStrings(w, "\n", indent, commented, "[[", combinedKey, "]]\n")
 | 
			
		||||
					bytesCount += int64(writtenBytesCount)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return bytesCount, err
 | 
			
		||||
					}
 | 
			
		||||
 | 
			
		||||
					bytesCount, err = subTree.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, compactComments, parentCommented || t.commented || subTree.commented)
 | 
			
		||||
					if err != nil {
 | 
			
		||||
						return bytesCount, err
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		default: // Simple
 | 
			
		||||
			k := node.key
 | 
			
		||||
			v, ok := t.values[k].(*tomlValue)
 | 
			
		||||
			if !ok {
 | 
			
		||||
				return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k])
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			var commented string
 | 
			
		||||
			if parentCommented || t.commented || v.commented {
 | 
			
		||||
				commented = "# "
 | 
			
		||||
			}
 | 
			
		||||
			repr, err := tomlValueStringRepresentation(v, commented, indent, ord, arraysOneElementPerLine)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return bytesCount, err
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if v.comment != "" {
 | 
			
		||||
				comment := strings.Replace(v.comment, "\n", "\n"+indent+"#", -1)
 | 
			
		||||
				start := "# "
 | 
			
		||||
				if strings.HasPrefix(comment, "#") {
 | 
			
		||||
					start = ""
 | 
			
		||||
				}
 | 
			
		||||
				if !compactComments {
 | 
			
		||||
					writtenBytesCountComment, errc := writeStrings(w, "\n")
 | 
			
		||||
					bytesCount += int64(writtenBytesCountComment)
 | 
			
		||||
					if errc != nil {
 | 
			
		||||
						return bytesCount, errc
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				writtenBytesCountComment, errc := writeStrings(w, indent, start, comment, "\n")
 | 
			
		||||
				bytesCount += int64(writtenBytesCountComment)
 | 
			
		||||
				if errc != nil {
 | 
			
		||||
					return bytesCount, errc
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			quotedKey := quoteKeyIfNeeded(k)
 | 
			
		||||
			writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n")
 | 
			
		||||
			bytesCount += int64(writtenBytesCount)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return bytesCount, err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return bytesCount, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// quote a key if it does not fit the bare key format (A-Za-z0-9_-)
 | 
			
		||||
// quoted keys use the same rules as strings
 | 
			
		||||
func quoteKeyIfNeeded(k string) string {
 | 
			
		||||
	// when encoding a map with the 'quoteMapKeys' option enabled, the tree will contain
 | 
			
		||||
	// keys that have already been quoted.
 | 
			
		||||
	// not an ideal situation, but good enough of a stop gap.
 | 
			
		||||
	if len(k) >= 2 && k[0] == '"' && k[len(k)-1] == '"' {
 | 
			
		||||
		return k
 | 
			
		||||
	}
 | 
			
		||||
	isBare := true
 | 
			
		||||
	for _, r := range k {
 | 
			
		||||
		if !isValidBareChar(r) {
 | 
			
		||||
			isBare = false
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if isBare {
 | 
			
		||||
		return k
 | 
			
		||||
	}
 | 
			
		||||
	return quoteKey(k)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func quoteKey(k string) string {
 | 
			
		||||
	return "\"" + encodeTomlString(k) + "\""
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func writeStrings(w io.Writer, s ...string) (int, error) {
 | 
			
		||||
	var n int
 | 
			
		||||
	for i := range s {
 | 
			
		||||
		b, err := io.WriteString(w, s[i])
 | 
			
		||||
		n += b
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			return n, err
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return n, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// WriteTo encode the Tree as Toml and writes it to the writer w.
 | 
			
		||||
// Returns the number of bytes written in case of success, or an error if anything happened.
 | 
			
		||||
func (t *Tree) WriteTo(w io.Writer) (int64, error) {
 | 
			
		||||
	return t.writeTo(w, "", "", 0, false)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToTomlString generates a human-readable representation of the current tree.
 | 
			
		||||
// Output spans multiple lines, and is suitable for ingest by a TOML parser.
 | 
			
		||||
// If the conversion cannot be performed, ToString returns a non-nil error.
 | 
			
		||||
func (t *Tree) ToTomlString() (string, error) {
 | 
			
		||||
	b, err := t.Marshal()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return "", err
 | 
			
		||||
	}
 | 
			
		||||
	return string(b), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String generates a human-readable representation of the current tree.
 | 
			
		||||
// Alias of ToString. Present to implement the fmt.Stringer interface.
 | 
			
		||||
func (t *Tree) String() string {
 | 
			
		||||
	result, _ := t.ToTomlString()
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ToMap recursively generates a representation of the tree using Go built-in structures.
 | 
			
		||||
// The following types are used:
 | 
			
		||||
//
 | 
			
		||||
//	* bool
 | 
			
		||||
//	* float64
 | 
			
		||||
//	* int64
 | 
			
		||||
//	* string
 | 
			
		||||
//	* uint64
 | 
			
		||||
//	* time.Time
 | 
			
		||||
//	* map[string]interface{} (where interface{} is any of this list)
 | 
			
		||||
//	* []interface{} (where interface{} is any of this list)
 | 
			
		||||
func (t *Tree) ToMap() map[string]interface{} {
 | 
			
		||||
	result := map[string]interface{}{}
 | 
			
		||||
 | 
			
		||||
	for k, v := range t.values {
 | 
			
		||||
		switch node := v.(type) {
 | 
			
		||||
		case []*Tree:
 | 
			
		||||
			var array []interface{}
 | 
			
		||||
			for _, item := range node {
 | 
			
		||||
				array = append(array, item.ToMap())
 | 
			
		||||
			}
 | 
			
		||||
			result[k] = array
 | 
			
		||||
		case *Tree:
 | 
			
		||||
			result[k] = node.ToMap()
 | 
			
		||||
		case *tomlValue:
 | 
			
		||||
			result[k] = tomlValueToGo(node.value)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return result
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func tomlValueToGo(v interface{}) interface{} {
 | 
			
		||||
	if tree, ok := v.(*Tree); ok {
 | 
			
		||||
		return tree.ToMap()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	rv := reflect.ValueOf(v)
 | 
			
		||||
 | 
			
		||||
	if rv.Kind() != reflect.Slice {
 | 
			
		||||
		return v
 | 
			
		||||
	}
 | 
			
		||||
	values := make([]interface{}, rv.Len())
 | 
			
		||||
	for i := 0; i < rv.Len(); i++ {
 | 
			
		||||
		item := rv.Index(i).Interface()
 | 
			
		||||
		values[i] = tomlValueToGo(item)
 | 
			
		||||
	}
 | 
			
		||||
	return values
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								vendor/github.com/pelletier/go-toml/tomltree_writepub.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/pelletier/go-toml/tomltree_writepub.go
									
									
									
										generated
									
									
										vendored
									
									
								
							@@ -1,6 +0,0 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
// ValueStringRepresentation transforms an interface{} value into its toml string representation.
 | 
			
		||||
func ValueStringRepresentation(v interface{}, commented string, indent string, ord MarshalOrder, arraysOneElementPerLine bool) (string, error) {
 | 
			
		||||
	return tomlValueStringRepresentation(v, commented, indent, ord, arraysOneElementPerLine)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										4
									
								
								vendor/github.com/pelletier/go-toml/v2/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								vendor/github.com/pelletier/go-toml/v2/.gitattributes
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
* text=auto
 | 
			
		||||
 | 
			
		||||
benchmark/benchmark.toml text eol=lf
 | 
			
		||||
testdata/** text eol=lf
 | 
			
		||||
@@ -3,3 +3,4 @@ fuzz/
 | 
			
		||||
cmd/tomll/tomll
 | 
			
		||||
cmd/tomljson/tomljson
 | 
			
		||||
cmd/tomltestgen/tomltestgen
 | 
			
		||||
dist
 | 
			
		||||
							
								
								
									
										84
									
								
								vendor/github.com/pelletier/go-toml/v2/.golangci.toml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								vendor/github.com/pelletier/go-toml/v2/.golangci.toml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,84 @@
 | 
			
		||||
[service]
 | 
			
		||||
golangci-lint-version =  "1.39.0"
 | 
			
		||||
 | 
			
		||||
[linters-settings.wsl]
 | 
			
		||||
allow-assign-and-anything = true
 | 
			
		||||
 | 
			
		||||
[linters-settings.exhaustive]
 | 
			
		||||
default-signifies-exhaustive = true
 | 
			
		||||
 | 
			
		||||
[linters]
 | 
			
		||||
disable-all = true
 | 
			
		||||
enable = [
 | 
			
		||||
    "asciicheck",
 | 
			
		||||
    "bodyclose",
 | 
			
		||||
    "cyclop",
 | 
			
		||||
    "deadcode",
 | 
			
		||||
    "depguard",
 | 
			
		||||
    "dogsled",
 | 
			
		||||
    "dupl",
 | 
			
		||||
    "durationcheck",
 | 
			
		||||
    "errcheck",
 | 
			
		||||
    "errorlint",
 | 
			
		||||
    "exhaustive",
 | 
			
		||||
    # "exhaustivestruct",
 | 
			
		||||
    "exportloopref",
 | 
			
		||||
    "forbidigo",
 | 
			
		||||
    # "forcetypeassert",
 | 
			
		||||
    "funlen",
 | 
			
		||||
    "gci",
 | 
			
		||||
    # "gochecknoglobals",
 | 
			
		||||
    "gochecknoinits",
 | 
			
		||||
    "gocognit",
 | 
			
		||||
    "goconst",
 | 
			
		||||
    "gocritic",
 | 
			
		||||
    "gocyclo",
 | 
			
		||||
    "godot",
 | 
			
		||||
    "godox",
 | 
			
		||||
    # "goerr113",
 | 
			
		||||
    "gofmt",
 | 
			
		||||
    "gofumpt",
 | 
			
		||||
    "goheader",
 | 
			
		||||
    "goimports",
 | 
			
		||||
    "golint",
 | 
			
		||||
    "gomnd",
 | 
			
		||||
    # "gomoddirectives",
 | 
			
		||||
    "gomodguard",
 | 
			
		||||
    "goprintffuncname",
 | 
			
		||||
    "gosec",
 | 
			
		||||
    "gosimple",
 | 
			
		||||
    "govet",
 | 
			
		||||
    # "ifshort",
 | 
			
		||||
    "importas",
 | 
			
		||||
    "ineffassign",
 | 
			
		||||
    "lll",
 | 
			
		||||
    "makezero",
 | 
			
		||||
    "misspell",
 | 
			
		||||
    "nakedret",
 | 
			
		||||
    "nestif",
 | 
			
		||||
    "nilerr",
 | 
			
		||||
    # "nlreturn",
 | 
			
		||||
    "noctx",
 | 
			
		||||
    "nolintlint",
 | 
			
		||||
    #"paralleltest",
 | 
			
		||||
    "prealloc",
 | 
			
		||||
    "predeclared",
 | 
			
		||||
    "revive",
 | 
			
		||||
    "rowserrcheck",
 | 
			
		||||
    "sqlclosecheck",
 | 
			
		||||
    "staticcheck",
 | 
			
		||||
    "structcheck",
 | 
			
		||||
    "stylecheck",
 | 
			
		||||
    # "testpackage",
 | 
			
		||||
    "thelper",
 | 
			
		||||
    "tparallel",
 | 
			
		||||
    "typecheck",
 | 
			
		||||
    "unconvert",
 | 
			
		||||
    "unparam",
 | 
			
		||||
    "unused",
 | 
			
		||||
    "varcheck",
 | 
			
		||||
    "wastedassign",
 | 
			
		||||
    "whitespace",
 | 
			
		||||
    # "wrapcheck",
 | 
			
		||||
    # "wsl"
 | 
			
		||||
]
 | 
			
		||||
							
								
								
									
										126
									
								
								vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										126
									
								
								vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,126 @@
 | 
			
		||||
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
 | 
			
		||||
      - linux_riscv64
 | 
			
		||||
      - 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
 | 
			
		||||
      - linux_riscv64
 | 
			
		||||
      - 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_riscv64
 | 
			
		||||
      - 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
 | 
			
		||||
							
								
								
									
										196
									
								
								vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										196
									
								
								vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,196 @@
 | 
			
		||||
# Contributing
 | 
			
		||||
 | 
			
		||||
Thank you for your interest in go-toml! We appreciate you considering
 | 
			
		||||
contributing to go-toml!
 | 
			
		||||
 | 
			
		||||
The main goal is the project is to provide an easy-to-use and efficient TOML
 | 
			
		||||
implementation for Go that gets the job done and gets out of your way – dealing
 | 
			
		||||
with TOML is probably not the central piece of your project.
 | 
			
		||||
 | 
			
		||||
As the single maintainer of go-toml, time is scarce. All help, big or small, is
 | 
			
		||||
more than welcomed!
 | 
			
		||||
 | 
			
		||||
## Ask questions
 | 
			
		||||
 | 
			
		||||
Any question you may have, somebody else might have it too. Always feel free to
 | 
			
		||||
ask them on the [discussion board][discussions]. We will try to answer them as
 | 
			
		||||
clearly and quickly as possible, time permitting.
 | 
			
		||||
 | 
			
		||||
Asking questions also helps us identify areas where the documentation needs
 | 
			
		||||
improvement, or new features that weren't envisioned before. Sometimes, a
 | 
			
		||||
seemingly innocent question leads to the fix of a bug. Don't hesitate and ask
 | 
			
		||||
away!
 | 
			
		||||
 | 
			
		||||
[discussions]: https://github.com/pelletier/go-toml/discussions
 | 
			
		||||
 | 
			
		||||
## Improve the documentation
 | 
			
		||||
 | 
			
		||||
The best way to share your knowledge and experience with go-toml is to improve
 | 
			
		||||
the documentation. Fix a typo, clarify an interface, add an example, anything
 | 
			
		||||
goes!
 | 
			
		||||
 | 
			
		||||
The documentation is present in the [README][readme] and thorough the source
 | 
			
		||||
code. On release, it gets updated on [pkg.go.dev][pkg.go.dev]. To make a change
 | 
			
		||||
to the documentation, create a pull request with your proposed changes. For
 | 
			
		||||
simple changes like that, the easiest way to go is probably the "Fork this
 | 
			
		||||
project and edit the file" button on Github, displayed at the top right of the
 | 
			
		||||
file. Unless it's a trivial change (for example a typo), provide a little bit of
 | 
			
		||||
context in your pull request description or commit message.
 | 
			
		||||
 | 
			
		||||
## Report a bug
 | 
			
		||||
 | 
			
		||||
Found a bug! Sorry to hear that :(. Help us and other track them down and fix by
 | 
			
		||||
reporting it. [File a new bug report][bug-report] on the [issues
 | 
			
		||||
tracker][issues-tracker]. The template should provide enough guidance on what to
 | 
			
		||||
include. When in doubt: add more details! By reducing ambiguity and providing
 | 
			
		||||
more information, it decreases back and forth and saves everyone time.
 | 
			
		||||
 | 
			
		||||
## Code changes
 | 
			
		||||
 | 
			
		||||
Want to contribute a patch? Very happy to hear that!
 | 
			
		||||
 | 
			
		||||
First, some high-level rules:
 | 
			
		||||
 | 
			
		||||
- A short proposal with some POC code is better than a lengthy piece of text
 | 
			
		||||
  with no code. Code speaks louder than words. That being said, bigger changes
 | 
			
		||||
  should probably start with a [discussion][discussions].
 | 
			
		||||
- No backward-incompatible patch will be accepted unless discussed. Sometimes
 | 
			
		||||
  it's hard, but we try not to break people's programs unless we absolutely have
 | 
			
		||||
  to.
 | 
			
		||||
- If you are writing a new feature or extending an existing one, make sure to
 | 
			
		||||
  write some documentation.
 | 
			
		||||
- Bug fixes need to be accompanied with regression tests.
 | 
			
		||||
- New code needs to be tested.
 | 
			
		||||
- Your commit messages need to explain why the change is needed, even if already
 | 
			
		||||
  included in the PR description.
 | 
			
		||||
 | 
			
		||||
It does sound like a lot, but those best practices are here to save time overall
 | 
			
		||||
and continuously improve the quality of the project, which is something everyone
 | 
			
		||||
benefits from.
 | 
			
		||||
 | 
			
		||||
### Get started
 | 
			
		||||
 | 
			
		||||
The fairly standard code contribution process looks like that:
 | 
			
		||||
 | 
			
		||||
1. [Fork the project][fork].
 | 
			
		||||
2. Make your changes, commit on any branch you like.
 | 
			
		||||
3. [Open up a pull request][pull-request]
 | 
			
		||||
4. Review, potential ask for changes.
 | 
			
		||||
5. Merge.
 | 
			
		||||
 | 
			
		||||
Feel free to ask for help! You can create draft pull requests to gather
 | 
			
		||||
some early feedback!
 | 
			
		||||
 | 
			
		||||
### Run the tests
 | 
			
		||||
 | 
			
		||||
You can run tests for go-toml using Go's test tool: `go test -race ./...`.
 | 
			
		||||
 | 
			
		||||
During the pull request process, all tests will be ran on Linux, Windows, and
 | 
			
		||||
MacOS on the last two versions of Go.
 | 
			
		||||
 | 
			
		||||
However, given GitHub's new policy to _not_ run Actions on pull requests until a
 | 
			
		||||
maintainer clicks on button, it is highly recommended that you run them locally
 | 
			
		||||
as you make changes.
 | 
			
		||||
 | 
			
		||||
### Check coverage
 | 
			
		||||
 | 
			
		||||
We use `go tool cover` to compute test coverage. Most code editors have a way to
 | 
			
		||||
run and display code coverage, but at the end of the day, we do this:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
go test -covermode=atomic -coverprofile=coverage.out
 | 
			
		||||
go tool cover -func=coverage.out
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
and verify that the overall percentage of tested code does not go down. This is
 | 
			
		||||
a requirement. As a rule of thumb, all lines of code touched by your changes
 | 
			
		||||
should be covered. On Unix you can use `./ci.sh coverage -d v2` to check if your
 | 
			
		||||
code lowers the coverage.
 | 
			
		||||
 | 
			
		||||
### Verify performance
 | 
			
		||||
 | 
			
		||||
Go-toml aims to stay efficient. We rely on a set of scenarios executed with Go's
 | 
			
		||||
builtin benchmark systems. Because of their noisy nature, containers provided by
 | 
			
		||||
Github Actions cannot be reliably used for benchmarking. As a result, you are
 | 
			
		||||
responsible for checking that your changes do not incur a performance penalty.
 | 
			
		||||
You can run their following to execute benchmarks:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
go test ./... -bench=. -count=10
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Benchmark results should be compared against each other with
 | 
			
		||||
[benchstat][benchstat]. Typical flow looks like this:
 | 
			
		||||
 | 
			
		||||
1. On the `v2` branch, run `go test ./... -bench=. -count 10` and save output to
 | 
			
		||||
   a file (for example `old.txt`).
 | 
			
		||||
2. Make some code changes.
 | 
			
		||||
3. Run `go test ....` again, and save the output to an other file (for example
 | 
			
		||||
   `new.txt`).
 | 
			
		||||
4. Run `benchstat old.txt new.txt` to check that time/op does not go up in any
 | 
			
		||||
   test.
 | 
			
		||||
 | 
			
		||||
On Unix you can use `./ci.sh benchmark -d v2` to verify how your code impacts
 | 
			
		||||
performance.
 | 
			
		||||
 | 
			
		||||
It is highly encouraged to add the benchstat results to your pull request
 | 
			
		||||
description. Pull requests that lower performance will receive more scrutiny.
 | 
			
		||||
 | 
			
		||||
[benchstat]: https://pkg.go.dev/golang.org/x/perf/cmd/benchstat
 | 
			
		||||
 | 
			
		||||
### Style
 | 
			
		||||
 | 
			
		||||
Try to look around and follow the same format and structure as the rest of the
 | 
			
		||||
code. We enforce using `go fmt` on the whole code base.
 | 
			
		||||
 | 
			
		||||
---
 | 
			
		||||
 | 
			
		||||
## Maintainers-only
 | 
			
		||||
 | 
			
		||||
### Merge pull request
 | 
			
		||||
 | 
			
		||||
Checklist:
 | 
			
		||||
 | 
			
		||||
- Passing CI.
 | 
			
		||||
- 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
 | 
			
		||||
   nice and clean.
 | 
			
		||||
3. Make sure the commit title is clear and contains the PR number (#123).
 | 
			
		||||
 | 
			
		||||
### New release
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
[pkg.go.dev]: https://pkg.go.dev/github.com/pelletier/go-toml
 | 
			
		||||
[readme]: ./README.md
 | 
			
		||||
[fork]: https://help.github.com/articles/fork-a-repo
 | 
			
		||||
[pull-request]: https://help.github.com/en/articles/creating-a-pull-request
 | 
			
		||||
[new-release]: https://github.com/pelletier/go-toml/releases/new
 | 
			
		||||
[gh]: https://github.com/cli/cli
 | 
			
		||||
[pr-labels]: https://github.com/pelletier/go-toml/blob/v2/.github/release.yml
 | 
			
		||||
							
								
								
									
										5
									
								
								vendor/github.com/pelletier/go-toml/v2/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/pelletier/go-toml/v2/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
			
		||||
FROM scratch
 | 
			
		||||
ENV PATH "$PATH:/bin"
 | 
			
		||||
COPY tomll /bin/tomll
 | 
			
		||||
COPY tomljson /bin/tomljson
 | 
			
		||||
COPY jsontoml /bin/jsontoml
 | 
			
		||||
							
								
								
									
										22
									
								
								vendor/github.com/pelletier/go-toml/v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/pelletier/go-toml/v2/LICENSE
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,22 @@
 | 
			
		||||
The MIT License (MIT)
 | 
			
		||||
 | 
			
		||||
go-toml v2
 | 
			
		||||
Copyright (c) 2021 - 2023 Thomas Pelletier
 | 
			
		||||
 | 
			
		||||
Permission is hereby granted, free of charge, to any person obtaining a copy
 | 
			
		||||
of this software and associated documentation files (the "Software"), to deal
 | 
			
		||||
in the Software without restriction, including without limitation the rights
 | 
			
		||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 | 
			
		||||
copies of the Software, and to permit persons to whom the Software is
 | 
			
		||||
furnished to do so, subject to the following conditions:
 | 
			
		||||
 | 
			
		||||
The above copyright notice and this permission notice shall be included in all
 | 
			
		||||
copies or substantial portions of the Software.
 | 
			
		||||
 | 
			
		||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | 
			
		||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | 
			
		||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 | 
			
		||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 | 
			
		||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 | 
			
		||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | 
			
		||||
SOFTWARE.
 | 
			
		||||
							
								
								
									
										575
									
								
								vendor/github.com/pelletier/go-toml/v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										575
									
								
								vendor/github.com/pelletier/go-toml/v2/README.md
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,575 @@
 | 
			
		||||
# go-toml v2
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
 | 
			
		||||
[💬 Anything else](https://github.com/pelletier/go-toml/discussions)
 | 
			
		||||
 | 
			
		||||
## Documentation
 | 
			
		||||
 | 
			
		||||
Full API, examples, and implementation notes are available in the Go
 | 
			
		||||
documentation.
 | 
			
		||||
 | 
			
		||||
[](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
 | 
			
		||||
 | 
			
		||||
As much as possible, this library is designed to behave similarly as the
 | 
			
		||||
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. 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 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.DisallowUnknownFields
 | 
			
		||||
 | 
			
		||||
### Contextualized errors
 | 
			
		||||
 | 
			
		||||
When most decoding errors occur, go-toml returns [`DecodeError`][decode-err],
 | 
			
		||||
which contains a human readable contextualized version of the error. For
 | 
			
		||||
example:
 | 
			
		||||
 | 
			
		||||
```
 | 
			
		||||
1| [server]
 | 
			
		||||
2| path = 100
 | 
			
		||||
 |        ~~~ cannot decode TOML integer into struct field toml_test.Server.Path of type string
 | 
			
		||||
3| port = 50
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[decode-err]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#DecodeError
 | 
			
		||||
 | 
			
		||||
### Local date and time support
 | 
			
		||||
 | 
			
		||||
TOML supports native [local date/times][ldt]. It allows to represent a given
 | 
			
		||||
date, time, or date-time without relation to a timezone or offset. To support
 | 
			
		||||
this use-case, go-toml provides [`LocalDate`][tld], [`LocalTime`][tlt], and
 | 
			
		||||
[`LocalDateTime`][tldt]. Those types can be transformed to and from `time.Time`,
 | 
			
		||||
making them convenient yet unambiguous structures for their respective TOML
 | 
			
		||||
representation.
 | 
			
		||||
 | 
			
		||||
[ldt]: https://toml.io/en/v1.0.0#local-date-time
 | 
			
		||||
[tld]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDate
 | 
			
		||||
[tlt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalTime
 | 
			
		||||
[tldt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDateTime
 | 
			
		||||
 | 
			
		||||
### Commented config
 | 
			
		||||
 | 
			
		||||
Since TOML is often used for configuration files, go-toml can emit documents
 | 
			
		||||
annotated with [comments and commented-out values][comments-example]. For
 | 
			
		||||
example, it can generate the following file:
 | 
			
		||||
 | 
			
		||||
```toml
 | 
			
		||||
# Host IP to connect to.
 | 
			
		||||
host = '127.0.0.1'
 | 
			
		||||
# Port of the remote server.
 | 
			
		||||
port = 4242
 | 
			
		||||
 | 
			
		||||
# Encryption parameters (optional)
 | 
			
		||||
# [TLS]
 | 
			
		||||
# cipher = 'AEAD-AES128-GCM-SHA256'
 | 
			
		||||
# version = 'TLS 1.3'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[comments-example]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Marshal-Commented
 | 
			
		||||
 | 
			
		||||
## Getting started
 | 
			
		||||
 | 
			
		||||
Given the following struct, let's see how to read it and write it as TOML:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
type MyConfig struct {
 | 
			
		||||
      Version int
 | 
			
		||||
      Name    string
 | 
			
		||||
      Tags    []string
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
### Unmarshaling
 | 
			
		||||
 | 
			
		||||
[`Unmarshal`][unmarshal] reads a TOML document and fills a Go structure with its
 | 
			
		||||
content. For example:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
doc := `
 | 
			
		||||
version = 2
 | 
			
		||||
name = "go-toml"
 | 
			
		||||
tags = ["go", "toml"]
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
var cfg MyConfig
 | 
			
		||||
err := toml.Unmarshal([]byte(doc), &cfg)
 | 
			
		||||
if err != nil {
 | 
			
		||||
      panic(err)
 | 
			
		||||
}
 | 
			
		||||
fmt.Println("version:", cfg.Version)
 | 
			
		||||
fmt.Println("name:", cfg.Name)
 | 
			
		||||
fmt.Println("tags:", cfg.Tags)
 | 
			
		||||
 | 
			
		||||
// Output:
 | 
			
		||||
// version: 2
 | 
			
		||||
// name: go-toml
 | 
			
		||||
// tags: [go toml]
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[unmarshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Unmarshal
 | 
			
		||||
 | 
			
		||||
### Marshaling
 | 
			
		||||
 | 
			
		||||
[`Marshal`][marshal] is the opposite of Unmarshal: it represents a Go structure
 | 
			
		||||
as a TOML document:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
cfg := MyConfig{
 | 
			
		||||
      Version: 2,
 | 
			
		||||
      Name:    "go-toml",
 | 
			
		||||
      Tags:    []string{"go", "toml"},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
b, err := toml.Marshal(cfg)
 | 
			
		||||
if err != nil {
 | 
			
		||||
      panic(err)
 | 
			
		||||
}
 | 
			
		||||
fmt.Println(string(b))
 | 
			
		||||
 | 
			
		||||
// Output:
 | 
			
		||||
// Version = 2
 | 
			
		||||
// Name = 'go-toml'
 | 
			
		||||
// Tags = ['go', 'toml']
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[marshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Marshal
 | 
			
		||||
 | 
			
		||||
## Unstable API
 | 
			
		||||
 | 
			
		||||
This API does not yet follow the backward compatibility guarantees of this
 | 
			
		||||
library. They provide early access to features that may have rough edges or an
 | 
			
		||||
API subject to change.
 | 
			
		||||
 | 
			
		||||
### Parser
 | 
			
		||||
 | 
			
		||||
Parser is the unstable API that allows iterative parsing of a TOML document at
 | 
			
		||||
the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable.
 | 
			
		||||
 | 
			
		||||
## 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
 | 
			
		||||
how to get the original behavior when possible.
 | 
			
		||||
 | 
			
		||||
### Decoding / Unmarshal
 | 
			
		||||
 | 
			
		||||
#### Automatic field name guessing
 | 
			
		||||
 | 
			
		||||
When unmarshaling to a struct, if a key in the TOML document does not exactly
 | 
			
		||||
match the name of a struct field or any of the `toml`-tagged field, v1 tries
 | 
			
		||||
multiple variations of the key ([code][v1-keys]).
 | 
			
		||||
 | 
			
		||||
V2 instead does a case-insensitive matching, like `encoding/json`.
 | 
			
		||||
 | 
			
		||||
This could impact you if you are relying on casing to differentiate two fields,
 | 
			
		||||
and one of them is a not using the `toml` struct tag. The recommended solution
 | 
			
		||||
is to be specific about tag names for those fields using the `toml` struct tag.
 | 
			
		||||
 | 
			
		||||
[v1-keys]: https://github.com/pelletier/go-toml/blob/a2e52561804c6cd9392ebf0048ca64fe4af67a43/marshal.go#L775-L781
 | 
			
		||||
 | 
			
		||||
#### Ignore preexisting value in interface
 | 
			
		||||
 | 
			
		||||
When decoding into a non-nil `interface{}`, go-toml v1 uses the type of the
 | 
			
		||||
element in the interface to decode the object. For example:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
type inner struct {
 | 
			
		||||
  B interface{}
 | 
			
		||||
}
 | 
			
		||||
type doc struct {
 | 
			
		||||
  A interface{}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
d := doc{
 | 
			
		||||
  A: inner{
 | 
			
		||||
    B: "Before",
 | 
			
		||||
  },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
data := `
 | 
			
		||||
[A]
 | 
			
		||||
B = "After"
 | 
			
		||||
`
 | 
			
		||||
 | 
			
		||||
toml.Unmarshal([]byte(data), &d)
 | 
			
		||||
fmt.Printf("toml v1: %#v\n", d)
 | 
			
		||||
 | 
			
		||||
// toml v1: main.doc{A:main.inner{B:"After"}}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In this case, field `A` is of type `interface{}`, containing a `inner` struct.
 | 
			
		||||
V1 sees that type and uses it when decoding the object.
 | 
			
		||||
 | 
			
		||||
When decoding an object into an `interface{}`, V2 instead disregards whatever
 | 
			
		||||
value the `interface{}` may contain and replaces it with a
 | 
			
		||||
`map[string]interface{}`. With the same data structure as above, here is what
 | 
			
		||||
the result looks like:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
toml.Unmarshal([]byte(data), &d)
 | 
			
		||||
fmt.Printf("toml v2: %#v\n", d)
 | 
			
		||||
 | 
			
		||||
// toml v2: main.doc{A:map[string]interface {}{"B":"After"}}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is to match `encoding/json`'s behavior. There is no way to make the v2
 | 
			
		||||
decoder behave like v1.
 | 
			
		||||
 | 
			
		||||
#### Values out of array bounds ignored
 | 
			
		||||
 | 
			
		||||
When decoding into an array, v1 returns an error when the number of elements
 | 
			
		||||
contained in the doc is superior to the capacity of the array. For example:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
type doc struct {
 | 
			
		||||
  A [2]string
 | 
			
		||||
}
 | 
			
		||||
d := doc{}
 | 
			
		||||
err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
 | 
			
		||||
fmt.Println(err)
 | 
			
		||||
 | 
			
		||||
// (1, 1): unmarshal: TOML array length (3) exceeds destination array length (2)
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
In the same situation, v2 ignores the last value:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d)
 | 
			
		||||
fmt.Println("err:", err, "d:", d)
 | 
			
		||||
// err: <nil> d: {[one two]}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
This is to match `encoding/json`'s behavior. There is no way to make the v2
 | 
			
		||||
decoder behave like v1.
 | 
			
		||||
 | 
			
		||||
#### Support for `toml.Unmarshaler` has been dropped
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
V1 emits struct fields order alphabetically by default. V2 struct fields are
 | 
			
		||||
emitted in order they are defined. For example:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
type S struct {
 | 
			
		||||
	B string
 | 
			
		||||
	A string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
data := S{
 | 
			
		||||
	B: "B",
 | 
			
		||||
	A: "A",
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
b, _ := tomlv1.Marshal(data)
 | 
			
		||||
fmt.Println("v1:\n" + string(b))
 | 
			
		||||
 | 
			
		||||
b, _ = tomlv2.Marshal(data)
 | 
			
		||||
fmt.Println("v2:\n" + string(b))
 | 
			
		||||
 | 
			
		||||
// Output:
 | 
			
		||||
// v1:
 | 
			
		||||
// A = "A"
 | 
			
		||||
// B = "B"
 | 
			
		||||
 | 
			
		||||
// v2:
 | 
			
		||||
// B = 'B'
 | 
			
		||||
// A = 'A'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
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, 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{
 | 
			
		||||
		"key": "value",
 | 
			
		||||
	},
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
b, _ := tomlv1.Marshal(data)
 | 
			
		||||
fmt.Println("v1:\n" + string(b))
 | 
			
		||||
 | 
			
		||||
b, _ = tomlv2.Marshal(data)
 | 
			
		||||
fmt.Println("v2:\n" + string(b))
 | 
			
		||||
 | 
			
		||||
buf := bytes.Buffer{}
 | 
			
		||||
enc := tomlv2.NewEncoder(&buf)
 | 
			
		||||
enc.SetIndentTables(true)
 | 
			
		||||
enc.Encode(data)
 | 
			
		||||
fmt.Println("v2 Encoder:\n" + string(buf.Bytes()))
 | 
			
		||||
 | 
			
		||||
// Output:
 | 
			
		||||
// v1:
 | 
			
		||||
//
 | 
			
		||||
// [table]
 | 
			
		||||
//   key = "value"
 | 
			
		||||
//
 | 
			
		||||
// v2:
 | 
			
		||||
// [table]
 | 
			
		||||
// key = 'value'
 | 
			
		||||
//
 | 
			
		||||
//
 | 
			
		||||
// v2 Encoder:
 | 
			
		||||
// [table]
 | 
			
		||||
//   key = 'value'
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
[sit]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Encoder.SetIndentTables
 | 
			
		||||
 | 
			
		||||
#### Keys and strings are single quoted
 | 
			
		||||
 | 
			
		||||
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. 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.
 | 
			
		||||
 | 
			
		||||
#### `TextMarshaler` emits as a string, not TOML
 | 
			
		||||
 | 
			
		||||
Types that implement [`encoding.TextMarshaler`][tm] can emit arbitrary TOML in
 | 
			
		||||
v1. The encoder would append the result to the output directly. In v2 the result
 | 
			
		||||
is wrapped in a string. As a result, this interface cannot be implemented by the
 | 
			
		||||
root object.
 | 
			
		||||
 | 
			
		||||
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`, `commented`, and `omitempty`. For example:
 | 
			
		||||
 | 
			
		||||
```go
 | 
			
		||||
type doc struct {
 | 
			
		||||
	// v1
 | 
			
		||||
	F string `toml:"field" multiline:"true" omitempty:"true" commented:"true"`
 | 
			
		||||
	// v2
 | 
			
		||||
	F string `toml:"field,multiline,omitempty,commented"`
 | 
			
		||||
}
 | 
			
		||||
```
 | 
			
		||||
 | 
			
		||||
Has a result, the `Encoder.SetTag*` methods have been removed, as there is just
 | 
			
		||||
one tag now.
 | 
			
		||||
 | 
			
		||||
#### `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](https://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).
 | 
			
		||||
							
								
								
									
										280
									
								
								vendor/github.com/pelletier/go-toml/v2/ci.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										280
									
								
								vendor/github.com/pelletier/go-toml/v2/ci.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,280 @@
 | 
			
		||||
#!/usr/bin/env bash
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
stderr() {
 | 
			
		||||
    echo "$@" 1>&2
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
usage() {
 | 
			
		||||
    b=$(basename "$0")
 | 
			
		||||
    echo $b: ERROR: "$@" 1>&2
 | 
			
		||||
 | 
			
		||||
    cat 1>&2 <<EOF
 | 
			
		||||
 | 
			
		||||
DESCRIPTION
 | 
			
		||||
 | 
			
		||||
    $(basename "$0") is the script to run continuous integration commands for
 | 
			
		||||
    go-toml on unix.
 | 
			
		||||
 | 
			
		||||
    Requires Go and Git to be available in the PATH. Expects to be ran from the
 | 
			
		||||
    root of go-toml's Git repository.
 | 
			
		||||
 | 
			
		||||
USAGE
 | 
			
		||||
 | 
			
		||||
    $b COMMAND [OPTIONS...]
 | 
			
		||||
 | 
			
		||||
COMMANDS
 | 
			
		||||
 | 
			
		||||
benchmark [OPTIONS...] [BRANCH]
 | 
			
		||||
 | 
			
		||||
    Run benchmarks.
 | 
			
		||||
 | 
			
		||||
    ARGUMENTS
 | 
			
		||||
 | 
			
		||||
        BRANCH Optional. Defines which Git branch to use when running
 | 
			
		||||
               benchmarks.
 | 
			
		||||
 | 
			
		||||
    OPTIONS
 | 
			
		||||
 | 
			
		||||
        -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.
 | 
			
		||||
 | 
			
		||||
    ARGUMENTS
 | 
			
		||||
 | 
			
		||||
        BRANCH  Optional. Defines which Git branch to use when reporting
 | 
			
		||||
                coverage. Defaults to HEAD.
 | 
			
		||||
 | 
			
		||||
    OPTIONS
 | 
			
		||||
 | 
			
		||||
        -d      Compare coverage of HEAD with the one of BRANCH. In this form,
 | 
			
		||||
                the BRANCH argument is required. Exit code is non-zero when
 | 
			
		||||
                coverage percentage decreased.
 | 
			
		||||
EOF
 | 
			
		||||
    exit 1
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
cover() {
 | 
			
		||||
    branch="${1}"
 | 
			
		||||
    dir="$(mktemp -d)"
 | 
			
		||||
 | 
			
		||||
    stderr "Executing coverage for ${branch} at ${dir}"
 | 
			
		||||
 | 
			
		||||
    if [ "${branch}" = "HEAD" ]; then
 | 
			
		||||
	    cp -r . "${dir}/"
 | 
			
		||||
    else
 | 
			
		||||
	    git worktree add "$dir" "$branch"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    pushd "$dir"
 | 
			
		||||
    go test -covermode=atomic  -coverpkg=./... -coverprofile=coverage.out.tmp ./...
 | 
			
		||||
    cat coverage.out.tmp | grep -v fuzz | grep -v testsuite | grep -v tomltestgen | grep -v gotoml-test-decoder > coverage.out
 | 
			
		||||
    go tool cover -func=coverage.out
 | 
			
		||||
    echo "Coverage profile for ${branch}: ${dir}/coverage.out" >&2
 | 
			
		||||
    popd
 | 
			
		||||
 | 
			
		||||
    if [ "${branch}" != "HEAD" ]; then
 | 
			
		||||
	    git worktree remove --force "$dir"
 | 
			
		||||
    fi
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
coverage() {
 | 
			
		||||
    case "$1" in
 | 
			
		||||
	-d)
 | 
			
		||||
	    shift
 | 
			
		||||
	    target="${1?Need to provide a target branch argument}"
 | 
			
		||||
 | 
			
		||||
	    output_dir="$(mktemp -d)"
 | 
			
		||||
	    target_out="${output_dir}/target.txt"
 | 
			
		||||
	    head_out="${output_dir}/head.txt"
 | 
			
		||||
	    
 | 
			
		||||
	    cover "${target}" > "${target_out}"
 | 
			
		||||
	    cover "HEAD" > "${head_out}"
 | 
			
		||||
 | 
			
		||||
	    cat "${target_out}"
 | 
			
		||||
	    cat "${head_out}"
 | 
			
		||||
 | 
			
		||||
	    echo ""
 | 
			
		||||
 | 
			
		||||
	    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!";
 | 
			
		||||
 | 
			
		||||
            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
 | 
			
		||||
	    ;;
 | 
			
		||||
    esac
 | 
			
		||||
 | 
			
		||||
    cover "${1-HEAD}"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bench() {
 | 
			
		||||
    branch="${1}"
 | 
			
		||||
    out="${2}"
 | 
			
		||||
    replace="${3}"
 | 
			
		||||
    dir="$(mktemp -d)"
 | 
			
		||||
 | 
			
		||||
    stderr "Executing benchmark for ${branch} at ${dir}"
 | 
			
		||||
 | 
			
		||||
    if [ "${branch}" = "HEAD" ]; then
 | 
			
		||||
    	cp -r . "${dir}/"
 | 
			
		||||
    else
 | 
			
		||||
	    git worktree add "$dir" "$branch"
 | 
			
		||||
    fi
 | 
			
		||||
 | 
			
		||||
    pushd "$dir"
 | 
			
		||||
 | 
			
		||||
    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
 | 
			
		||||
	    git worktree remove --force "$dir"
 | 
			
		||||
    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=`fmktemp ${target}`
 | 
			
		||||
        bench "${target}" "${old}"
 | 
			
		||||
 | 
			
		||||
        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`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
case "$1" in
 | 
			
		||||
    coverage) shift; coverage $@;;
 | 
			
		||||
    benchmark) shift; benchmark $@;;
 | 
			
		||||
    *) usage "bad argument $1";;
 | 
			
		||||
esac
 | 
			
		||||
							
								
								
									
										550
									
								
								vendor/github.com/pelletier/go-toml/v2/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										550
									
								
								vendor/github.com/pelletier/go-toml/v2/decode.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,550 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"math"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/unstable"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func parseInteger(b []byte) (int64, error) {
 | 
			
		||||
	if len(b) > 2 && b[0] == '0' {
 | 
			
		||||
		switch b[1] {
 | 
			
		||||
		case 'x':
 | 
			
		||||
			return parseIntHex(b)
 | 
			
		||||
		case 'b':
 | 
			
		||||
			return parseIntBin(b)
 | 
			
		||||
		case 'o':
 | 
			
		||||
			return parseIntOct(b)
 | 
			
		||||
		default:
 | 
			
		||||
			panic(fmt.Errorf("invalid base '%c', should have been checked by scanIntOrFloat", b[1]))
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return parseIntDec(b)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseLocalDate(b []byte) (LocalDate, error) {
 | 
			
		||||
	// full-date      = date-fullyear "-" date-month "-" date-mday
 | 
			
		||||
	// date-fullyear  = 4DIGIT
 | 
			
		||||
	// date-month     = 2DIGIT  ; 01-12
 | 
			
		||||
	// date-mday      = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on month/year
 | 
			
		||||
	var date LocalDate
 | 
			
		||||
 | 
			
		||||
	if len(b) != 10 || b[4] != '-' || b[7] != '-' {
 | 
			
		||||
		return date, unstable.NewParserError(b, "dates are expected to have the format YYYY-MM-DD")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	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.Day, err = parseDecimalDigits(b[8:10])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return LocalDate{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !isValidDate(date.Year, date.Month, date.Day) {
 | 
			
		||||
		return LocalDate{}, unstable.NewParserError(b, "impossible date")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return date, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseDecimalDigits(b []byte) (int, error) {
 | 
			
		||||
	v := 0
 | 
			
		||||
 | 
			
		||||
	for i, c := range b {
 | 
			
		||||
		if c < '0' || c > '9' {
 | 
			
		||||
			return 0, unstable.NewParserError(b[i:i+1], "expected digit (0-9)")
 | 
			
		||||
		}
 | 
			
		||||
		v *= 10
 | 
			
		||||
		v += int(c - '0')
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return v, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseDateTime(b []byte) (time.Time, error) {
 | 
			
		||||
	// offset-date-time = full-date time-delim full-time
 | 
			
		||||
	// full-time      = partial-time time-offset
 | 
			
		||||
	// time-offset    = "Z" / time-numoffset
 | 
			
		||||
	// time-numoffset = ( "+" / "-" ) time-hour ":" time-minute
 | 
			
		||||
 | 
			
		||||
	dt, b, err := parseLocalDateTime(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return time.Time{}, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var zone *time.Location
 | 
			
		||||
 | 
			
		||||
	if len(b) == 0 {
 | 
			
		||||
		// parser should have checked that when assigning the date time node
 | 
			
		||||
		panic("date time should have a timezone")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b[0] == 'Z' || b[0] == 'z' {
 | 
			
		||||
		b = b[1:]
 | 
			
		||||
		zone = time.UTC
 | 
			
		||||
	} else {
 | 
			
		||||
		const dateTimeByteLen = 6
 | 
			
		||||
		if len(b) != dateTimeByteLen {
 | 
			
		||||
			return time.Time{}, unstable.NewParserError(b, "invalid date-time timezone")
 | 
			
		||||
		}
 | 
			
		||||
		var direction int
 | 
			
		||||
		switch b[0] {
 | 
			
		||||
		case '-':
 | 
			
		||||
			direction = -1
 | 
			
		||||
		case '+':
 | 
			
		||||
			direction = +1
 | 
			
		||||
		default:
 | 
			
		||||
			return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset character")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if b[3] != ':' {
 | 
			
		||||
			return time.Time{}, unstable.NewParserError(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{}, unstable.NewParserError(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{}, unstable.NewParserError(b[:1], "invalid timezone offset minutes")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		seconds := direction * (hours*3600 + minutes*60)
 | 
			
		||||
		if seconds == 0 {
 | 
			
		||||
			zone = time.UTC
 | 
			
		||||
		} else {
 | 
			
		||||
			zone = time.FixedZone("", seconds)
 | 
			
		||||
		}
 | 
			
		||||
		b = b[dateTimeByteLen:]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if len(b) > 0 {
 | 
			
		||||
		return time.Time{}, unstable.NewParserError(b, "extra bytes at the end of the timezone")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t := time.Date(
 | 
			
		||||
		dt.Year,
 | 
			
		||||
		time.Month(dt.Month),
 | 
			
		||||
		dt.Day,
 | 
			
		||||
		dt.Hour,
 | 
			
		||||
		dt.Minute,
 | 
			
		||||
		dt.Second,
 | 
			
		||||
		dt.Nanosecond,
 | 
			
		||||
		zone)
 | 
			
		||||
 | 
			
		||||
	return t, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) {
 | 
			
		||||
	var dt LocalDateTime
 | 
			
		||||
 | 
			
		||||
	const localDateTimeByteMinLen = 11
 | 
			
		||||
	if len(b) < localDateTimeByteMinLen {
 | 
			
		||||
		return dt, nil, unstable.NewParserError(b, "local datetimes are expected to have the format YYYY-MM-DDTHH:MM:SS[.NNNNNNNNN]")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	date, err := parseLocalDate(b[:10])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return dt, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	dt.LocalDate = date
 | 
			
		||||
 | 
			
		||||
	sep := b[10]
 | 
			
		||||
	if sep != 'T' && sep != ' ' && sep != 't' {
 | 
			
		||||
		return dt, nil, unstable.NewParserError(b[10:11], "datetime separator is expected to be T or a space")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t, rest, err := parseLocalTime(b[11:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return dt, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	dt.LocalTime = t
 | 
			
		||||
 | 
			
		||||
	return dt, rest, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// parseLocalTime is a bit different because it also returns the remaining
 | 
			
		||||
// []byte that is didn't need. This is to allow parseDateTime to parse those
 | 
			
		||||
// remaining bytes as a timezone.
 | 
			
		||||
func parseLocalTime(b []byte) (LocalTime, []byte, error) {
 | 
			
		||||
	var (
 | 
			
		||||
		nspow = [10]int{0, 1e8, 1e7, 1e6, 1e5, 1e4, 1e3, 1e2, 1e1, 1e0}
 | 
			
		||||
		t     LocalTime
 | 
			
		||||
	)
 | 
			
		||||
 | 
			
		||||
	// check if b matches to have expected format HH:MM:SS[.NNNNNN]
 | 
			
		||||
	const localTimeByteLen = 8
 | 
			
		||||
	if len(b) < localTimeByteLen {
 | 
			
		||||
		return t, nil, unstable.NewParserError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	var err error
 | 
			
		||||
 | 
			
		||||
	t.Hour, err = parseDecimalDigits(b[0:2])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return t, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t.Hour > 23 {
 | 
			
		||||
		return t, nil, unstable.NewParserError(b[0:2], "hour cannot be greater 23")
 | 
			
		||||
	}
 | 
			
		||||
	if b[2] != ':' {
 | 
			
		||||
		return t, nil, unstable.NewParserError(b[2:3], "expecting colon between hours and minutes")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Minute, err = parseDecimalDigits(b[3:5])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return t, nil, err
 | 
			
		||||
	}
 | 
			
		||||
	if t.Minute > 59 {
 | 
			
		||||
		return t, nil, unstable.NewParserError(b[3:5], "minutes cannot be greater 59")
 | 
			
		||||
	}
 | 
			
		||||
	if b[5] != ':' {
 | 
			
		||||
		return t, nil, unstable.NewParserError(b[5:6], "expecting colon between minutes and seconds")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	t.Second, err = parseDecimalDigits(b[6:8])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return t, nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if t.Second > 60 {
 | 
			
		||||
		return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	b = b[8:]
 | 
			
		||||
 | 
			
		||||
	if len(b) >= 1 && b[0] == '.' {
 | 
			
		||||
		frac := 0
 | 
			
		||||
		precision := 0
 | 
			
		||||
		digits := 0
 | 
			
		||||
 | 
			
		||||
		for i, c := range b[1:] {
 | 
			
		||||
			if !isDigit(c) {
 | 
			
		||||
				if i == 0 {
 | 
			
		||||
					return t, nil, unstable.NewParserError(b[0:1], "need at least one digit after fraction point")
 | 
			
		||||
				}
 | 
			
		||||
				break
 | 
			
		||||
			}
 | 
			
		||||
			digits++
 | 
			
		||||
 | 
			
		||||
			const maxFracPrecision = 9
 | 
			
		||||
			if i >= maxFracPrecision {
 | 
			
		||||
				// 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')
 | 
			
		||||
			precision++
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if precision == 0 {
 | 
			
		||||
			return t, nil, unstable.NewParserError(b[:1], "nanoseconds need at least one digit")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		t.Nanosecond = frac * nspow[precision]
 | 
			
		||||
		t.Precision = precision
 | 
			
		||||
 | 
			
		||||
		return t, b[1+digits:], nil
 | 
			
		||||
	}
 | 
			
		||||
	return t, b, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//nolint:cyclop
 | 
			
		||||
func parseFloat(b []byte) (float64, error) {
 | 
			
		||||
	if len(b) == 4 && (b[0] == '+' || b[0] == '-') && b[1] == 'n' && b[2] == 'a' && b[3] == 'n' {
 | 
			
		||||
		return math.NaN(), nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	cleaned, err := checkAndRemoveUnderscoresFloats(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cleaned[0] == '.' {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "float cannot start with a dot")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if cleaned[len(cleaned)-1] == '.' {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "float cannot end with a dot")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	dotAlreadySeen := false
 | 
			
		||||
	for i, c := range cleaned {
 | 
			
		||||
		if c == '.' {
 | 
			
		||||
			if dotAlreadySeen {
 | 
			
		||||
				return 0, unstable.NewParserError(b[i:i+1], "float can have at most one decimal point")
 | 
			
		||||
			}
 | 
			
		||||
			if !isDigit(cleaned[i-1]) {
 | 
			
		||||
				return 0, unstable.NewParserError(b[i-1:i+1], "float decimal point must be preceded by a digit")
 | 
			
		||||
			}
 | 
			
		||||
			if !isDigit(cleaned[i+1]) {
 | 
			
		||||
				return 0, unstable.NewParserError(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' && len(cleaned) > start+1 && isDigit(cleaned[start+1]) {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "float integer part cannot have leading zeroes")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	f, err := strconv.ParseFloat(string(cleaned), 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "unable to parse float: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return f, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseIntHex(b []byte) (int64, error) {
 | 
			
		||||
	cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i, err := strconv.ParseInt(string(cleaned), 16, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "couldn't parse hexadecimal number: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseIntOct(b []byte) (int64, error) {
 | 
			
		||||
	cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i, err := strconv.ParseInt(string(cleaned), 8, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "couldn't parse octal number: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseIntBin(b []byte) (int64, error) {
 | 
			
		||||
	cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:])
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i, err := strconv.ParseInt(string(cleaned), 2, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "couldn't parse binary number: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isSign(b byte) bool {
 | 
			
		||||
	return b == '+' || b == '-'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func parseIntDec(b []byte) (int64, error) {
 | 
			
		||||
	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, unstable.NewParserError(b, "leading zero not allowed on decimal number")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	i, err := strconv.ParseInt(string(cleaned), 10, 64)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return 0, unstable.NewParserError(b, "couldn't parse decimal number: %w", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return i, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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, unstable.NewParserError(b[start:start+1], "number cannot start with underscore")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b[len(b)-1] == '_' {
 | 
			
		||||
		return nil, unstable.NewParserError(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, i, len(b))
 | 
			
		||||
	copy(cleaned, b)
 | 
			
		||||
 | 
			
		||||
	for i++; i < len(b); i++ {
 | 
			
		||||
		c := b[i]
 | 
			
		||||
		if c == '_' {
 | 
			
		||||
			if !before {
 | 
			
		||||
				return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores")
 | 
			
		||||
			}
 | 
			
		||||
			before = false
 | 
			
		||||
		} else {
 | 
			
		||||
			before = true
 | 
			
		||||
			cleaned = append(cleaned, c)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return cleaned, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) {
 | 
			
		||||
	if b[0] == '_' {
 | 
			
		||||
		return nil, unstable.NewParserError(b[0:1], "number cannot start with underscore")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b[len(b)-1] == '_' {
 | 
			
		||||
		return nil, unstable.NewParserError(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, unstable.NewParserError(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, unstable.NewParserError(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, unstable.NewParserError(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, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after decimal point")
 | 
			
		||||
			}
 | 
			
		||||
			if i > 0 && b[i-1] == '_' {
 | 
			
		||||
				return nil, unstable.NewParserError(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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isDigit(r byte) bool {
 | 
			
		||||
	return r >= '0' && r <= '9'
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										2
									
								
								vendor/github.com/pelletier/go-toml/v2/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/pelletier/go-toml/v2/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,2 @@
 | 
			
		||||
// Package toml is a library to read and write TOML documents.
 | 
			
		||||
package toml
 | 
			
		||||
							
								
								
									
										252
									
								
								vendor/github.com/pelletier/go-toml/v2/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								vendor/github.com/pelletier/go-toml/v2/errors.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,252 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strconv"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/internal/danger"
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/unstable"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// DecodeError represents an error encountered during the parsing or decoding
 | 
			
		||||
// of a TOML document.
 | 
			
		||||
//
 | 
			
		||||
// In addition to the error message, it contains the position in the document
 | 
			
		||||
// where it happened, as well as a human-readable representation that shows
 | 
			
		||||
// where the error occurred in the document.
 | 
			
		||||
type DecodeError struct {
 | 
			
		||||
	message string
 | 
			
		||||
	line    int
 | 
			
		||||
	column  int
 | 
			
		||||
	key     Key
 | 
			
		||||
 | 
			
		||||
	human string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// StrictMissingError occurs in a TOML document that does not have a
 | 
			
		||||
// corresponding field in the target value. It contains all the missing fields
 | 
			
		||||
// in Errors.
 | 
			
		||||
//
 | 
			
		||||
// Emitted by Decoder when DisallowUnknownFields() was called.
 | 
			
		||||
type StrictMissingError struct {
 | 
			
		||||
	// One error per field that could not be found.
 | 
			
		||||
	Errors []DecodeError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Error returns the canonical string for this error.
 | 
			
		||||
func (s *StrictMissingError) Error() string {
 | 
			
		||||
	return "strict mode: fields in the document are missing in the target struct"
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns a human readable description of all errors.
 | 
			
		||||
func (s *StrictMissingError) String() string {
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
 | 
			
		||||
	for i, e := range s.Errors {
 | 
			
		||||
		if i > 0 {
 | 
			
		||||
			buf.WriteString("\n---\n")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf.WriteString(e.String())
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return buf.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type Key []string
 | 
			
		||||
 | 
			
		||||
// Error returns the error message contained in the DecodeError.
 | 
			
		||||
func (e *DecodeError) Error() string {
 | 
			
		||||
	return "toml: " + e.message
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns the human-readable contextualized error. This string is multi-line.
 | 
			
		||||
func (e *DecodeError) String() string {
 | 
			
		||||
	return e.human
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Position returns the (line, column) pair indicating where the error
 | 
			
		||||
// occurred in the document. Positions are 1-indexed.
 | 
			
		||||
func (e *DecodeError) Position() (row int, column int) {
 | 
			
		||||
	return e.line, e.column
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key that was being processed when the error occurred. The key is present only
 | 
			
		||||
// if this DecodeError is part of a StrictMissingError.
 | 
			
		||||
func (e *DecodeError) Key() Key {
 | 
			
		||||
	return e.key
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// decodeErrorFromHighlight creates a DecodeError referencing a highlighted
 | 
			
		||||
// range of bytes from document.
 | 
			
		||||
//
 | 
			
		||||
// highlight needs to be a sub-slice of document, or this function panics.
 | 
			
		||||
//
 | 
			
		||||
// The function copies all bytes used in DecodeError, so that document and
 | 
			
		||||
// highlight can be freely deallocated.
 | 
			
		||||
//
 | 
			
		||||
//nolint:funlen
 | 
			
		||||
func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError {
 | 
			
		||||
	offset := danger.SubsliceOffset(document, de.Highlight)
 | 
			
		||||
 | 
			
		||||
	errMessage := de.Error()
 | 
			
		||||
	errLine, errColumn := positionAtEnd(document[:offset])
 | 
			
		||||
	before, after := linesOfContext(document, de.Highlight, offset, 3)
 | 
			
		||||
 | 
			
		||||
	var buf strings.Builder
 | 
			
		||||
 | 
			
		||||
	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))
 | 
			
		||||
		buf.WriteString("|")
 | 
			
		||||
 | 
			
		||||
		if len(before[i]) > 0 {
 | 
			
		||||
			buf.WriteString(" ")
 | 
			
		||||
			buf.Write(before[i])
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		buf.WriteRune('\n')
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Write the document line that contains the error.
 | 
			
		||||
 | 
			
		||||
	buf.WriteString(formatLineNumber(errLine, lineColumnWidth))
 | 
			
		||||
	buf.WriteString("| ")
 | 
			
		||||
 | 
			
		||||
	if len(before) > 0 {
 | 
			
		||||
		buf.Write(before[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf.Write(de.Highlight)
 | 
			
		||||
 | 
			
		||||
	if len(after) > 0 {
 | 
			
		||||
		buf.Write(after[0])
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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("| ")
 | 
			
		||||
 | 
			
		||||
	if len(before) > 0 {
 | 
			
		||||
		buf.WriteString(strings.Repeat(" ", len(before[0])))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	buf.WriteString(strings.Repeat("~", len(de.Highlight)))
 | 
			
		||||
 | 
			
		||||
	if len(errMessage) > 0 {
 | 
			
		||||
		buf.WriteString(" ")
 | 
			
		||||
		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
 | 
			
		||||
		buf.WriteString(formatLineNumber(line, lineColumnWidth))
 | 
			
		||||
		buf.WriteString("|")
 | 
			
		||||
 | 
			
		||||
		if len(after[i]) > 0 {
 | 
			
		||||
			buf.WriteString(" ")
 | 
			
		||||
			buf.Write(after[i])
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &DecodeError{
 | 
			
		||||
		message: errMessage,
 | 
			
		||||
		line:    errLine,
 | 
			
		||||
		column:  errColumn,
 | 
			
		||||
		key:     de.Key,
 | 
			
		||||
		human:   buf.String(),
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func formatLineNumber(line int, width int) string {
 | 
			
		||||
	format := "%" + strconv.Itoa(width) + "d"
 | 
			
		||||
 | 
			
		||||
	return fmt.Sprintf(format, line)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func linesOfContext(document []byte, highlight []byte, offset int, linesAround int) ([][]byte, [][]byte) {
 | 
			
		||||
	return beforeLines(document, offset, linesAround), afterLines(document, highlight, offset, linesAround)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func beforeLines(document []byte, offset int, linesAround int) [][]byte {
 | 
			
		||||
	var beforeLines [][]byte
 | 
			
		||||
 | 
			
		||||
	// Walk the document backward from the highlight to find previous lines
 | 
			
		||||
	// of context.
 | 
			
		||||
	rest := document[:offset]
 | 
			
		||||
backward:
 | 
			
		||||
	for o := len(rest) - 1; o >= 0 && len(beforeLines) <= linesAround && len(rest) > 0; {
 | 
			
		||||
		switch {
 | 
			
		||||
		case rest[o] == '\n':
 | 
			
		||||
			// handle individual lines
 | 
			
		||||
			beforeLines = append(beforeLines, rest[o+1:])
 | 
			
		||||
			rest = rest[:o]
 | 
			
		||||
			o = len(rest) - 1
 | 
			
		||||
		case o == 0:
 | 
			
		||||
			// add the first line only if it's non-empty
 | 
			
		||||
			beforeLines = append(beforeLines, rest)
 | 
			
		||||
 | 
			
		||||
			break backward
 | 
			
		||||
		default:
 | 
			
		||||
			o--
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return beforeLines
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func afterLines(document []byte, highlight []byte, offset int, linesAround int) [][]byte {
 | 
			
		||||
	var afterLines [][]byte
 | 
			
		||||
 | 
			
		||||
	// Walk the document forward from the highlight to find the following
 | 
			
		||||
	// lines of context.
 | 
			
		||||
	rest := document[offset+len(highlight):]
 | 
			
		||||
forward:
 | 
			
		||||
	for o := 0; o < len(rest) && len(afterLines) <= linesAround; {
 | 
			
		||||
		switch {
 | 
			
		||||
		case rest[o] == '\n':
 | 
			
		||||
			// handle individual lines
 | 
			
		||||
			afterLines = append(afterLines, rest[:o])
 | 
			
		||||
			rest = rest[o+1:]
 | 
			
		||||
			o = 0
 | 
			
		||||
 | 
			
		||||
		case o == len(rest)-1:
 | 
			
		||||
			// add last line only if it's non-empty
 | 
			
		||||
			afterLines = append(afterLines, rest)
 | 
			
		||||
 | 
			
		||||
			break forward
 | 
			
		||||
		default:
 | 
			
		||||
			o++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return afterLines
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func positionAtEnd(b []byte) (row int, column int) {
 | 
			
		||||
	row = 1
 | 
			
		||||
	column = 1
 | 
			
		||||
 | 
			
		||||
	for _, c := range b {
 | 
			
		||||
		if c == '\n' {
 | 
			
		||||
			row++
 | 
			
		||||
			column = 1
 | 
			
		||||
		} else {
 | 
			
		||||
			column++
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										42
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,42 @@
 | 
			
		||||
package characters
 | 
			
		||||
 | 
			
		||||
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]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										199
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										199
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,199 @@
 | 
			
		||||
package characters
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
)
 | 
			
		||||
							
								
								
									
										65
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,65 @@
 | 
			
		||||
package danger
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const maxInt = uintptr(int(^uint(0) >> 1))
 | 
			
		||||
 | 
			
		||||
func SubsliceOffset(data []byte, subslice []byte) int {
 | 
			
		||||
	datap := (*reflect.SliceHeader)(unsafe.Pointer(&data))
 | 
			
		||||
	hlp := (*reflect.SliceHeader)(unsafe.Pointer(&subslice))
 | 
			
		||||
 | 
			
		||||
	if hlp.Data < datap.Data {
 | 
			
		||||
		panic(fmt.Errorf("subslice address (%d) is before data address (%d)", hlp.Data, datap.Data))
 | 
			
		||||
	}
 | 
			
		||||
	offset := hlp.Data - datap.Data
 | 
			
		||||
 | 
			
		||||
	if offset > maxInt {
 | 
			
		||||
		panic(fmt.Errorf("slice offset larger than int (%d)", offset))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	intoffset := int(offset)
 | 
			
		||||
 | 
			
		||||
	if intoffset > datap.Len {
 | 
			
		||||
		panic(fmt.Errorf("slice offset (%d) is farther than data length (%d)", intoffset, datap.Len))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if intoffset+hlp.Len > datap.Len {
 | 
			
		||||
		panic(fmt.Errorf("slice ends (%d+%d) is farther than data length (%d)", intoffset, hlp.Len, datap.Len))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return intoffset
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func BytesRange(start []byte, end []byte) []byte {
 | 
			
		||||
	if start == nil || end == nil {
 | 
			
		||||
		panic("cannot call BytesRange with nil")
 | 
			
		||||
	}
 | 
			
		||||
	startp := (*reflect.SliceHeader)(unsafe.Pointer(&start))
 | 
			
		||||
	endp := (*reflect.SliceHeader)(unsafe.Pointer(&end))
 | 
			
		||||
 | 
			
		||||
	if startp.Data > endp.Data {
 | 
			
		||||
		panic(fmt.Errorf("start pointer address (%d) is after end pointer address (%d)", startp.Data, endp.Data))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	l := startp.Len
 | 
			
		||||
	endLen := int(endp.Data-startp.Data) + endp.Len
 | 
			
		||||
	if endLen > l {
 | 
			
		||||
		l = endLen
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if l > startp.Cap {
 | 
			
		||||
		panic(fmt.Errorf("range length is larger than capacity"))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										23
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -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])
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
package tracker
 | 
			
		||||
 | 
			
		||||
import "github.com/pelletier/go-toml/v2/unstable"
 | 
			
		||||
 | 
			
		||||
// KeyTracker is a tracker that keeps track of the current Key as the AST is
 | 
			
		||||
// walked.
 | 
			
		||||
type KeyTracker struct {
 | 
			
		||||
	k []string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateTable sets the state of the tracker with the AST table node.
 | 
			
		||||
func (t *KeyTracker) UpdateTable(node *unstable.Node) {
 | 
			
		||||
	t.reset()
 | 
			
		||||
	t.Push(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UpdateArrayTable sets the state of the tracker with the AST array table node.
 | 
			
		||||
func (t *KeyTracker) UpdateArrayTable(node *unstable.Node) {
 | 
			
		||||
	t.reset()
 | 
			
		||||
	t.Push(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Push the given key on the stack.
 | 
			
		||||
func (t *KeyTracker) Push(node *unstable.Node) {
 | 
			
		||||
	it := node.Key()
 | 
			
		||||
	for it.Next() {
 | 
			
		||||
		t.k = append(t.k, string(it.Node().Data))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Pop key from stack.
 | 
			
		||||
func (t *KeyTracker) Pop(node *unstable.Node) {
 | 
			
		||||
	it := node.Key()
 | 
			
		||||
	for it.Next() {
 | 
			
		||||
		t.k = t.k[:len(t.k)-1]
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key returns the current key
 | 
			
		||||
func (t *KeyTracker) Key() []string {
 | 
			
		||||
	k := make([]string, len(t.k))
 | 
			
		||||
	copy(k, t.k)
 | 
			
		||||
	return k
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (t *KeyTracker) reset() {
 | 
			
		||||
	t.k = t.k[:0]
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										356
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										356
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,356 @@
 | 
			
		||||
package tracker
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"bytes"
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"sync"
 | 
			
		||||
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/unstable"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type keyKind uint8
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	invalidKind keyKind = iota
 | 
			
		||||
	valueKind
 | 
			
		||||
	tableKind
 | 
			
		||||
	arrayTableKind
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func (k keyKind) String() string {
 | 
			
		||||
	switch k {
 | 
			
		||||
	case invalidKind:
 | 
			
		||||
		return "invalid"
 | 
			
		||||
	case valueKind:
 | 
			
		||||
		return "value"
 | 
			
		||||
	case tableKind:
 | 
			
		||||
		return "table"
 | 
			
		||||
	case arrayTableKind:
 | 
			
		||||
		return "array table"
 | 
			
		||||
	}
 | 
			
		||||
	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.
 | 
			
		||||
//
 | 
			
		||||
// 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 {
 | 
			
		||||
	entries    []entry
 | 
			
		||||
	currentIdx int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var pool sync.Pool
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type entry struct {
 | 
			
		||||
	// Use -1 to indicate no child or no sibling.
 | 
			
		||||
	child int
 | 
			
		||||
	next  int
 | 
			
		||||
 | 
			
		||||
	name     []byte
 | 
			
		||||
	kind     keyKind
 | 
			
		||||
	explicit bool
 | 
			
		||||
	kv       bool
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Remove all descendants of node at position idx.
 | 
			
		||||
func (s *SeenTracker) clear(idx int) {
 | 
			
		||||
	if idx >= len(s.entries) {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.entries[parentIdx].child = idx
 | 
			
		||||
 | 
			
		||||
	return idx
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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.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 *unstable.Node) error {
 | 
			
		||||
	if s.entries == nil {
 | 
			
		||||
		s.reset()
 | 
			
		||||
	}
 | 
			
		||||
	switch node.Kind {
 | 
			
		||||
	case unstable.KeyValue:
 | 
			
		||||
		return s.checkKeyValue(node)
 | 
			
		||||
	case unstable.Table:
 | 
			
		||||
		return s.checkTable(node)
 | 
			
		||||
	case unstable.ArrayTable:
 | 
			
		||||
		return s.checkArrayTable(node)
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Errorf("this should not be a top level node type: %s", node.Kind))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SeenTracker) checkTable(node *unstable.Node) error {
 | 
			
		||||
	if s.currentIdx >= 0 {
 | 
			
		||||
		s.setExplicitFlag(s.currentIdx)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	it := node.Key()
 | 
			
		||||
 | 
			
		||||
	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.IsLast() {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		parentIdx = idx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k := it.Node().Data
 | 
			
		||||
	idx := s.find(parentIdx, k)
 | 
			
		||||
 | 
			
		||||
	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 s.entries[idx].explicit {
 | 
			
		||||
			return fmt.Errorf("toml: table %s already exists", string(k))
 | 
			
		||||
		}
 | 
			
		||||
		s.entries[idx].explicit = true
 | 
			
		||||
	} else {
 | 
			
		||||
		idx = s.create(parentIdx, k, tableKind, true, false)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.currentIdx = idx
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SeenTracker) checkArrayTable(node *unstable.Node) error {
 | 
			
		||||
	if s.currentIdx >= 0 {
 | 
			
		||||
		s.setExplicitFlag(s.currentIdx)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	it := node.Key()
 | 
			
		||||
 | 
			
		||||
	parentIdx := 0
 | 
			
		||||
 | 
			
		||||
	for it.Next() {
 | 
			
		||||
		if it.IsLast() {
 | 
			
		||||
			break
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		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)
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		parentIdx = idx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	k := it.Node().Data
 | 
			
		||||
	idx := s.find(parentIdx, 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))
 | 
			
		||||
		}
 | 
			
		||||
		s.clear(idx)
 | 
			
		||||
	} else {
 | 
			
		||||
		idx = s.create(parentIdx, k, arrayTableKind, true, false)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.currentIdx = idx
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SeenTracker) checkKeyValue(node *unstable.Node) error {
 | 
			
		||||
	parentIdx := s.currentIdx
 | 
			
		||||
	it := node.Key()
 | 
			
		||||
 | 
			
		||||
	for it.Next() {
 | 
			
		||||
		k := it.Node().Data
 | 
			
		||||
 | 
			
		||||
		idx := s.find(parentIdx, k)
 | 
			
		||||
 | 
			
		||||
		if idx < 0 {
 | 
			
		||||
			idx = s.create(parentIdx, k, tableKind, false, true)
 | 
			
		||||
		} else {
 | 
			
		||||
			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))
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		parentIdx = idx
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.entries[parentIdx].kind = valueKind
 | 
			
		||||
 | 
			
		||||
	value := node.Value()
 | 
			
		||||
 | 
			
		||||
	switch value.Kind {
 | 
			
		||||
	case unstable.InlineTable:
 | 
			
		||||
		return s.checkInlineTable(value)
 | 
			
		||||
	case unstable.Array:
 | 
			
		||||
		return s.checkArray(value)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SeenTracker) checkArray(node *unstable.Node) error {
 | 
			
		||||
	it := node.Children()
 | 
			
		||||
	for it.Next() {
 | 
			
		||||
		n := it.Node()
 | 
			
		||||
		switch n.Kind {
 | 
			
		||||
		case unstable.InlineTable:
 | 
			
		||||
			err := s.checkInlineTable(n)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		case unstable.Array:
 | 
			
		||||
			err := s.checkArray(n)
 | 
			
		||||
			if err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *SeenTracker) checkInlineTable(node *unstable.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
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
			
		||||
package tracker
 | 
			
		||||
							
								
								
									
										122
									
								
								vendor/github.com/pelletier/go-toml/v2/localtime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										122
									
								
								vendor/github.com/pelletier/go-toml/v2/localtime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,122 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/unstable"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// LocalDate represents a calendar day in no specific timezone.
 | 
			
		||||
type LocalDate struct {
 | 
			
		||||
	Year  int
 | 
			
		||||
	Month int
 | 
			
		||||
	Day   int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 RFC 3339 representation of d.
 | 
			
		||||
func (d LocalDate) String() string {
 | 
			
		||||
	return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalText returns RFC 3339 representation of d.
 | 
			
		||||
func (d LocalDate) MarshalText() ([]byte, error) {
 | 
			
		||||
	return []byte(d.String()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// UnmarshalText parses b using RFC 3339 to fill d.
 | 
			
		||||
func (d *LocalDate) UnmarshalText(b []byte) error {
 | 
			
		||||
	res, err := parseLocalDate(b)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*d = res
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalText returns RFC 3339 representation of d.
 | 
			
		||||
func (d LocalTime) MarshalText() ([]byte, error) {
 | 
			
		||||
	return []byte(d.String()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 = unstable.NewParserError(left, "extra characters")
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
	*d = res
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LocalDateTime represents a time of a specific day in no specific timezone.
 | 
			
		||||
type LocalDateTime struct {
 | 
			
		||||
	LocalDate
 | 
			
		||||
	LocalTime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// String returns RFC 3339 representation of d.
 | 
			
		||||
func (d LocalDateTime) String() string {
 | 
			
		||||
	return d.LocalDate.String() + "T" + d.LocalTime.String()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// MarshalText returns RFC 3339 representation of d.
 | 
			
		||||
func (d LocalDateTime) MarshalText() ([]byte, error) {
 | 
			
		||||
	return []byte(d.String()), nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 = unstable.NewParserError(left, "extra characters")
 | 
			
		||||
	}
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	*d = res
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1090
									
								
								vendor/github.com/pelletier/go-toml/v2/marshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1090
									
								
								vendor/github.com/pelletier/go-toml/v2/marshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										107
									
								
								vendor/github.com/pelletier/go-toml/v2/strict.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										107
									
								
								vendor/github.com/pelletier/go-toml/v2/strict.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,107 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/internal/danger"
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/internal/tracker"
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/unstable"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type strict struct {
 | 
			
		||||
	Enabled bool
 | 
			
		||||
 | 
			
		||||
	// Tracks the current key being processed.
 | 
			
		||||
	key tracker.KeyTracker
 | 
			
		||||
 | 
			
		||||
	missing []unstable.ParserError
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) EnterTable(node *unstable.Node) {
 | 
			
		||||
	if !s.Enabled {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.key.UpdateTable(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) EnterArrayTable(node *unstable.Node) {
 | 
			
		||||
	if !s.Enabled {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.key.UpdateArrayTable(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) EnterKeyValue(node *unstable.Node) {
 | 
			
		||||
	if !s.Enabled {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.key.Push(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) ExitKeyValue(node *unstable.Node) {
 | 
			
		||||
	if !s.Enabled {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.key.Pop(node)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) MissingTable(node *unstable.Node) {
 | 
			
		||||
	if !s.Enabled {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.missing = append(s.missing, unstable.ParserError{
 | 
			
		||||
		Highlight: keyLocation(node),
 | 
			
		||||
		Message:   "missing table",
 | 
			
		||||
		Key:       s.key.Key(),
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) MissingField(node *unstable.Node) {
 | 
			
		||||
	if !s.Enabled {
 | 
			
		||||
		return
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	s.missing = append(s.missing, unstable.ParserError{
 | 
			
		||||
		Highlight: keyLocation(node),
 | 
			
		||||
		Message:   "missing field",
 | 
			
		||||
		Key:       s.key.Key(),
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (s *strict) Error(doc []byte) error {
 | 
			
		||||
	if !s.Enabled || len(s.missing) == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	err := &StrictMissingError{
 | 
			
		||||
		Errors: make([]DecodeError, 0, len(s.missing)),
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, derr := range s.missing {
 | 
			
		||||
		derr := derr
 | 
			
		||||
		err.Errors = append(err.Errors, *wrapDecodeError(doc, &derr))
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func keyLocation(node *unstable.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)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										243
									
								
								vendor/github.com/pelletier/go-toml/v2/toml.abnf
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										243
									
								
								vendor/github.com/pelletier/go-toml/v2/toml.abnf
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,243 @@
 | 
			
		||||
;; This document describes TOML's syntax, using the ABNF format (defined in
 | 
			
		||||
;; RFC 5234 -- https://www.ietf.org/rfc/rfc5234.txt).
 | 
			
		||||
;;
 | 
			
		||||
;; All valid TOML documents will match this description, however certain
 | 
			
		||||
;; invalid documents would need to be rejected as per the semantics described
 | 
			
		||||
;; in the supporting text description.
 | 
			
		||||
 | 
			
		||||
;; It is possible to try this grammar interactively, using instaparse.
 | 
			
		||||
;;     http://instaparse.mojombo.com/
 | 
			
		||||
;;
 | 
			
		||||
;; To do so, in the lower right, click on Options and change `:input-format` to
 | 
			
		||||
;; ':abnf'. Then paste this entire ABNF document into the grammar entry box
 | 
			
		||||
;; (above the options). Then you can type or paste a sample TOML document into
 | 
			
		||||
;; the beige box on the left. Tada!
 | 
			
		||||
 | 
			
		||||
;; Overall Structure
 | 
			
		||||
 | 
			
		||||
toml = expression *( newline expression )
 | 
			
		||||
 | 
			
		||||
expression =  ws [ comment ]
 | 
			
		||||
expression =/ ws keyval ws [ comment ]
 | 
			
		||||
expression =/ ws table ws [ comment ]
 | 
			
		||||
 | 
			
		||||
;; Whitespace
 | 
			
		||||
 | 
			
		||||
ws = *wschar
 | 
			
		||||
wschar =  %x20  ; Space
 | 
			
		||||
wschar =/ %x09  ; Horizontal tab
 | 
			
		||||
 | 
			
		||||
;; Newline
 | 
			
		||||
 | 
			
		||||
newline =  %x0A     ; LF
 | 
			
		||||
newline =/ %x0D.0A  ; CRLF
 | 
			
		||||
 | 
			
		||||
;; Comment
 | 
			
		||||
 | 
			
		||||
comment-start-symbol = %x23 ; #
 | 
			
		||||
non-ascii = %x80-D7FF / %xE000-10FFFF
 | 
			
		||||
non-eol = %x09 / %x20-7F / non-ascii
 | 
			
		||||
 | 
			
		||||
comment = comment-start-symbol *non-eol
 | 
			
		||||
 | 
			
		||||
;; Key-Value pairs
 | 
			
		||||
 | 
			
		||||
keyval = key keyval-sep val
 | 
			
		||||
 | 
			
		||||
key = simple-key / dotted-key
 | 
			
		||||
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
 | 
			
		||||
dotted-key = simple-key 1*( dot-sep simple-key )
 | 
			
		||||
 | 
			
		||||
dot-sep   = ws %x2E ws  ; . Period
 | 
			
		||||
keyval-sep = ws %x3D ws ; =
 | 
			
		||||
 | 
			
		||||
val = string / boolean / array / inline-table / date-time / float / integer
 | 
			
		||||
 | 
			
		||||
;; String
 | 
			
		||||
 | 
			
		||||
string = ml-basic-string / basic-string / ml-literal-string / literal-string
 | 
			
		||||
 | 
			
		||||
;; Basic String
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
escape = %x5C                   ; \
 | 
			
		||||
escape-seq-char =  %x22         ; "    quotation mark  U+0022
 | 
			
		||||
escape-seq-char =/ %x5C         ; \    reverse solidus U+005C
 | 
			
		||||
escape-seq-char =/ %x62         ; b    backspace       U+0008
 | 
			
		||||
escape-seq-char =/ %x66         ; f    form feed       U+000C
 | 
			
		||||
escape-seq-char =/ %x6E         ; n    line feed       U+000A
 | 
			
		||||
escape-seq-char =/ %x72         ; r    carriage return U+000D
 | 
			
		||||
escape-seq-char =/ %x74         ; t    tab             U+0009
 | 
			
		||||
escape-seq-char =/ %x75 4HEXDIG ; uXXXX                U+XXXX
 | 
			
		||||
escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX            U+XXXXXXXX
 | 
			
		||||
 | 
			
		||||
;; Multiline Basic String
 | 
			
		||||
 | 
			
		||||
ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body
 | 
			
		||||
                  ml-basic-string-delim
 | 
			
		||||
ml-basic-string-delim = 3quotation-mark
 | 
			
		||||
ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ]
 | 
			
		||||
 | 
			
		||||
mlb-content = mlb-char / newline / mlb-escaped-nl
 | 
			
		||||
mlb-char = mlb-unescaped / escaped
 | 
			
		||||
mlb-quotes = 1*2quotation-mark
 | 
			
		||||
mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
 | 
			
		||||
mlb-escaped-nl = escape ws newline *( wschar / newline )
 | 
			
		||||
 | 
			
		||||
;; Literal String
 | 
			
		||||
 | 
			
		||||
literal-string = apostrophe *literal-char apostrophe
 | 
			
		||||
 | 
			
		||||
apostrophe = %x27 ; ' apostrophe
 | 
			
		||||
 | 
			
		||||
literal-char = %x09 / %x20-26 / %x28-7E / non-ascii
 | 
			
		||||
 | 
			
		||||
;; Multiline Literal String
 | 
			
		||||
 | 
			
		||||
ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body
 | 
			
		||||
                    ml-literal-string-delim
 | 
			
		||||
ml-literal-string-delim = 3apostrophe
 | 
			
		||||
ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ]
 | 
			
		||||
 | 
			
		||||
mll-content = mll-char / newline
 | 
			
		||||
mll-char = %x09 / %x20-26 / %x28-7E / non-ascii
 | 
			
		||||
mll-quotes = 1*2apostrophe
 | 
			
		||||
 | 
			
		||||
;; Integer
 | 
			
		||||
 | 
			
		||||
integer = dec-int / hex-int / oct-int / bin-int
 | 
			
		||||
 | 
			
		||||
minus = %x2D                       ; -
 | 
			
		||||
plus = %x2B                        ; +
 | 
			
		||||
underscore = %x5F                  ; _
 | 
			
		||||
digit1-9 = %x31-39                 ; 1-9
 | 
			
		||||
digit0-7 = %x30-37                 ; 0-7
 | 
			
		||||
digit0-1 = %x30-31                 ; 0-1
 | 
			
		||||
 | 
			
		||||
hex-prefix = %x30.78               ; 0x
 | 
			
		||||
oct-prefix = %x30.6F               ; 0o
 | 
			
		||||
bin-prefix = %x30.62               ; 0b
 | 
			
		||||
 | 
			
		||||
dec-int = [ minus / plus ] unsigned-dec-int
 | 
			
		||||
unsigned-dec-int = DIGIT / digit1-9 1*( DIGIT / underscore DIGIT )
 | 
			
		||||
 | 
			
		||||
hex-int = hex-prefix HEXDIG *( HEXDIG / underscore HEXDIG )
 | 
			
		||||
oct-int = oct-prefix digit0-7 *( digit0-7 / underscore digit0-7 )
 | 
			
		||||
bin-int = bin-prefix digit0-1 *( digit0-1 / underscore digit0-1 )
 | 
			
		||||
 | 
			
		||||
;; Float
 | 
			
		||||
 | 
			
		||||
float = float-int-part ( exp / frac [ exp ] )
 | 
			
		||||
float =/ special-float
 | 
			
		||||
 | 
			
		||||
float-int-part = dec-int
 | 
			
		||||
frac = decimal-point zero-prefixable-int
 | 
			
		||||
decimal-point = %x2E               ; .
 | 
			
		||||
zero-prefixable-int = DIGIT *( DIGIT / underscore DIGIT )
 | 
			
		||||
 | 
			
		||||
exp = "e" float-exp-part
 | 
			
		||||
float-exp-part = [ minus / plus ] zero-prefixable-int
 | 
			
		||||
 | 
			
		||||
special-float = [ minus / plus ] ( inf / nan )
 | 
			
		||||
inf = %x69.6e.66  ; inf
 | 
			
		||||
nan = %x6e.61.6e  ; nan
 | 
			
		||||
 | 
			
		||||
;; Boolean
 | 
			
		||||
 | 
			
		||||
boolean = true / false
 | 
			
		||||
 | 
			
		||||
true    = %x74.72.75.65     ; true
 | 
			
		||||
false   = %x66.61.6C.73.65  ; false
 | 
			
		||||
 | 
			
		||||
;; Date and Time (as defined in RFC 3339)
 | 
			
		||||
 | 
			
		||||
date-time      = offset-date-time / local-date-time / local-date / local-time
 | 
			
		||||
 | 
			
		||||
date-fullyear  = 4DIGIT
 | 
			
		||||
date-month     = 2DIGIT  ; 01-12
 | 
			
		||||
date-mday      = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on month/year
 | 
			
		||||
time-delim     = "T" / %x20 ; T, t, or space
 | 
			
		||||
time-hour      = 2DIGIT  ; 00-23
 | 
			
		||||
time-minute    = 2DIGIT  ; 00-59
 | 
			
		||||
time-second    = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second rules
 | 
			
		||||
time-secfrac   = "." 1*DIGIT
 | 
			
		||||
time-numoffset = ( "+" / "-" ) time-hour ":" time-minute
 | 
			
		||||
time-offset    = "Z" / time-numoffset
 | 
			
		||||
 | 
			
		||||
partial-time   = time-hour ":" time-minute ":" time-second [ time-secfrac ]
 | 
			
		||||
full-date      = date-fullyear "-" date-month "-" date-mday
 | 
			
		||||
full-time      = partial-time time-offset
 | 
			
		||||
 | 
			
		||||
;; Offset Date-Time
 | 
			
		||||
 | 
			
		||||
offset-date-time = full-date time-delim full-time
 | 
			
		||||
 | 
			
		||||
;; Local Date-Time
 | 
			
		||||
 | 
			
		||||
local-date-time = full-date time-delim partial-time
 | 
			
		||||
 | 
			
		||||
;; Local Date
 | 
			
		||||
 | 
			
		||||
local-date = full-date
 | 
			
		||||
 | 
			
		||||
;; Local Time
 | 
			
		||||
 | 
			
		||||
local-time = partial-time
 | 
			
		||||
 | 
			
		||||
;; Array
 | 
			
		||||
 | 
			
		||||
array = array-open [ array-values ] ws-comment-newline array-close
 | 
			
		||||
 | 
			
		||||
array-open =  %x5B ; [
 | 
			
		||||
array-close = %x5D ; ]
 | 
			
		||||
 | 
			
		||||
array-values =  ws-comment-newline val ws-comment-newline array-sep array-values
 | 
			
		||||
array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ]
 | 
			
		||||
 | 
			
		||||
array-sep = %x2C  ; , Comma
 | 
			
		||||
 | 
			
		||||
ws-comment-newline = *( wschar / [ comment ] newline )
 | 
			
		||||
 | 
			
		||||
;; Table
 | 
			
		||||
 | 
			
		||||
table = std-table / array-table
 | 
			
		||||
 | 
			
		||||
;; Standard Table
 | 
			
		||||
 | 
			
		||||
std-table = std-table-open key std-table-close
 | 
			
		||||
 | 
			
		||||
std-table-open  = %x5B ws     ; [ Left square bracket
 | 
			
		||||
std-table-close = ws %x5D     ; ] Right square bracket
 | 
			
		||||
 | 
			
		||||
;; Inline Table
 | 
			
		||||
 | 
			
		||||
inline-table = inline-table-open [ inline-table-keyvals ] inline-table-close
 | 
			
		||||
 | 
			
		||||
inline-table-open  = %x7B ws     ; {
 | 
			
		||||
inline-table-close = ws %x7D     ; }
 | 
			
		||||
inline-table-sep   = ws %x2C ws  ; , Comma
 | 
			
		||||
 | 
			
		||||
inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ]
 | 
			
		||||
 | 
			
		||||
;; Array Table
 | 
			
		||||
 | 
			
		||||
array-table = array-table-open key array-table-close
 | 
			
		||||
 | 
			
		||||
array-table-open  = %x5B.5B ws  ; [[ Double left square bracket
 | 
			
		||||
array-table-close = ws %x5D.5D  ; ]] Double right square bracket
 | 
			
		||||
 | 
			
		||||
;; Built-in ABNF terms, reproduced here for clarity
 | 
			
		||||
 | 
			
		||||
ALPHA = %x41-5A / %x61-7A ; A-Z / a-z
 | 
			
		||||
DIGIT = %x30-39 ; 0-9
 | 
			
		||||
HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F"
 | 
			
		||||
							
								
								
									
										14
									
								
								vendor/github.com/pelletier/go-toml/v2/types.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								vendor/github.com/pelletier/go-toml/v2/types.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
package toml
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"encoding"
 | 
			
		||||
	"reflect"
 | 
			
		||||
	"time"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
var timeType = reflect.TypeOf((*time.Time)(nil)).Elem()
 | 
			
		||||
var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
 | 
			
		||||
var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
 | 
			
		||||
var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil))
 | 
			
		||||
var sliceInterfaceType = reflect.TypeOf([]interface{}(nil))
 | 
			
		||||
var stringType = reflect.TypeOf("")
 | 
			
		||||
							
								
								
									
										1264
									
								
								vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1264
									
								
								vendor/github.com/pelletier/go-toml/v2/unmarshaler.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										136
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/ast.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,136 @@
 | 
			
		||||
package unstable
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"unsafe"
 | 
			
		||||
 | 
			
		||||
	"github.com/pelletier/go-toml/v2/internal/danger"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Iterator over a sequence of nodes.
 | 
			
		||||
//
 | 
			
		||||
// Starts uninitialized, you need to call Next() first.
 | 
			
		||||
//
 | 
			
		||||
// For example:
 | 
			
		||||
//
 | 
			
		||||
//	it := n.Children()
 | 
			
		||||
//	for it.Next() {
 | 
			
		||||
//		n := it.Node()
 | 
			
		||||
//		// do something with n
 | 
			
		||||
//	}
 | 
			
		||||
type Iterator struct {
 | 
			
		||||
	started bool
 | 
			
		||||
	node    *Node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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
 | 
			
		||||
	} else if c.node.Valid() {
 | 
			
		||||
		c.node = c.node.Next()
 | 
			
		||||
	}
 | 
			
		||||
	return c.node.Valid()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// IsLast returns true if the current node of the iterator is the last
 | 
			
		||||
// one.  Subsequent calls to Next() will return false.
 | 
			
		||||
func (c *Iterator) IsLast() bool {
 | 
			
		||||
	return c.node.next == 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Node returns a pointer to the node pointed at by the iterator.
 | 
			
		||||
func (c *Iterator) Node() *Node {
 | 
			
		||||
	return c.node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Node in a TOML expression AST.
 | 
			
		||||
//
 | 
			
		||||
// Depending on Kind, its sequence of children should be interpreted
 | 
			
		||||
// differently.
 | 
			
		||||
//
 | 
			
		||||
//   - Array have one child per element in the array.
 | 
			
		||||
//   - InlineTable have one child per key-value in the table (each of kind
 | 
			
		||||
//     InlineTable).
 | 
			
		||||
//   - KeyValue have at least two children. The first one is the value. The rest
 | 
			
		||||
//     make a potentially dotted key.
 | 
			
		||||
//   - Table and ArrayTable's children represent a dotted key (same as
 | 
			
		||||
//     KeyValue, but without the first node being the value).
 | 
			
		||||
//
 | 
			
		||||
// When relevant, Raw describes the range of bytes this node is referring to in
 | 
			
		||||
// the input document. Use Parser.Raw() to retrieve the actual bytes.
 | 
			
		||||
type Node struct {
 | 
			
		||||
	Kind Kind
 | 
			
		||||
	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
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Range of bytes in the document.
 | 
			
		||||
type Range struct {
 | 
			
		||||
	Offset uint32
 | 
			
		||||
	Length uint32
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Next returns a pointer to the next node, or nil if there is no next node.
 | 
			
		||||
func (n *Node) Next() *Node {
 | 
			
		||||
	if n.next == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	ptr := unsafe.Pointer(n)
 | 
			
		||||
	size := unsafe.Sizeof(Node{})
 | 
			
		||||
	return (*Node)(danger.Stride(ptr, size, n.next))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Child returns a pointer to the first child node of this node. Other children
 | 
			
		||||
// can be accessed calling Next on the first child.  Returns an nil if this Node
 | 
			
		||||
// has no child.
 | 
			
		||||
func (n *Node) Child() *Node {
 | 
			
		||||
	if n.child == 0 {
 | 
			
		||||
		return nil
 | 
			
		||||
	}
 | 
			
		||||
	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 != nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Key returns the children 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:
 | 
			
		||||
		value := n.Child()
 | 
			
		||||
		if !value.Valid() {
 | 
			
		||||
			panic(fmt.Errorf("KeyValue should have at least two children"))
 | 
			
		||||
		}
 | 
			
		||||
		return Iterator{node: value.Next()}
 | 
			
		||||
	case Table, ArrayTable:
 | 
			
		||||
		return Iterator{node: n.Child()}
 | 
			
		||||
	default:
 | 
			
		||||
		panic(fmt.Errorf("Key() is not supported on a %s", n.Kind))
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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 {
 | 
			
		||||
	return n.Child()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Children returns an iterator over a node's children.
 | 
			
		||||
func (n *Node) Children() Iterator {
 | 
			
		||||
	return Iterator{node: n.Child()}
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										71
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/builder.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
package unstable
 | 
			
		||||
 | 
			
		||||
// root contains a full AST.
 | 
			
		||||
//
 | 
			
		||||
// It is immutable once constructed with Builder.
 | 
			
		||||
type root struct {
 | 
			
		||||
	nodes []Node
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Iterator over the top level nodes.
 | 
			
		||||
func (r *root) Iterator() Iterator {
 | 
			
		||||
	it := Iterator{}
 | 
			
		||||
	if len(r.nodes) > 0 {
 | 
			
		||||
		it.node = &r.nodes[0]
 | 
			
		||||
	}
 | 
			
		||||
	return it
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *root) at(idx reference) *Node {
 | 
			
		||||
	return &r.nodes[idx]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type reference int
 | 
			
		||||
 | 
			
		||||
const invalidReference reference = -1
 | 
			
		||||
 | 
			
		||||
func (r reference) Valid() bool {
 | 
			
		||||
	return r != invalidReference
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type builder struct {
 | 
			
		||||
	tree    root
 | 
			
		||||
	lastIdx int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) Tree() *root {
 | 
			
		||||
	return &b.tree
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) NodeAt(ref reference) *Node {
 | 
			
		||||
	return b.tree.at(ref)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) Reset() {
 | 
			
		||||
	b.tree.nodes = b.tree.nodes[:0]
 | 
			
		||||
	b.lastIdx = 0
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) Push(n Node) reference {
 | 
			
		||||
	b.lastIdx = len(b.tree.nodes)
 | 
			
		||||
	b.tree.nodes = append(b.tree.nodes, n)
 | 
			
		||||
	return reference(b.lastIdx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) PushAndChain(n Node) reference {
 | 
			
		||||
	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.lastIdx
 | 
			
		||||
	}
 | 
			
		||||
	b.lastIdx = newIdx
 | 
			
		||||
	return reference(b.lastIdx)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) AttachChild(parent reference, child reference) {
 | 
			
		||||
	b.tree.nodes[parent].child = int(child) - int(parent)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *builder) Chain(from reference, to reference) {
 | 
			
		||||
	b.tree.nodes[from].next = int(to) - int(from)
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										3
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/doc.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
// Package unstable provides APIs that do not meet the backward compatibility
 | 
			
		||||
// guarantees yet.
 | 
			
		||||
package unstable
 | 
			
		||||
							
								
								
									
										71
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/kind.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,71 @@
 | 
			
		||||
package unstable
 | 
			
		||||
 | 
			
		||||
import "fmt"
 | 
			
		||||
 | 
			
		||||
// Kind represents the type of TOML structure contained in a given Node.
 | 
			
		||||
type Kind int
 | 
			
		||||
 | 
			
		||||
const (
 | 
			
		||||
	// Meta
 | 
			
		||||
	Invalid Kind = iota
 | 
			
		||||
	Comment
 | 
			
		||||
	Key
 | 
			
		||||
 | 
			
		||||
	// Top level structures
 | 
			
		||||
	Table
 | 
			
		||||
	ArrayTable
 | 
			
		||||
	KeyValue
 | 
			
		||||
 | 
			
		||||
	// Containers values
 | 
			
		||||
	Array
 | 
			
		||||
	InlineTable
 | 
			
		||||
 | 
			
		||||
	// Values
 | 
			
		||||
	String
 | 
			
		||||
	Bool
 | 
			
		||||
	Float
 | 
			
		||||
	Integer
 | 
			
		||||
	LocalDate
 | 
			
		||||
	LocalTime
 | 
			
		||||
	LocalDateTime
 | 
			
		||||
	DateTime
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// String implementation of fmt.Stringer.
 | 
			
		||||
func (k Kind) String() string {
 | 
			
		||||
	switch k {
 | 
			
		||||
	case Invalid:
 | 
			
		||||
		return "Invalid"
 | 
			
		||||
	case Comment:
 | 
			
		||||
		return "Comment"
 | 
			
		||||
	case Key:
 | 
			
		||||
		return "Key"
 | 
			
		||||
	case Table:
 | 
			
		||||
		return "Table"
 | 
			
		||||
	case ArrayTable:
 | 
			
		||||
		return "ArrayTable"
 | 
			
		||||
	case KeyValue:
 | 
			
		||||
		return "KeyValue"
 | 
			
		||||
	case Array:
 | 
			
		||||
		return "Array"
 | 
			
		||||
	case InlineTable:
 | 
			
		||||
		return "InlineTable"
 | 
			
		||||
	case String:
 | 
			
		||||
		return "String"
 | 
			
		||||
	case Bool:
 | 
			
		||||
		return "Bool"
 | 
			
		||||
	case Float:
 | 
			
		||||
		return "Float"
 | 
			
		||||
	case Integer:
 | 
			
		||||
		return "Integer"
 | 
			
		||||
	case LocalDate:
 | 
			
		||||
		return "LocalDate"
 | 
			
		||||
	case LocalTime:
 | 
			
		||||
		return "LocalTime"
 | 
			
		||||
	case LocalDateTime:
 | 
			
		||||
		return "LocalDateTime"
 | 
			
		||||
	case DateTime:
 | 
			
		||||
		return "DateTime"
 | 
			
		||||
	}
 | 
			
		||||
	panic(fmt.Errorf("Kind.String() not implemented for '%d'", k))
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										1245
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1245
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/parser.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										270
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										270
									
								
								vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,270 @@
 | 
			
		||||
package unstable
 | 
			
		||||
 | 
			
		||||
import "github.com/pelletier/go-toml/v2/internal/characters"
 | 
			
		||||
 | 
			
		||||
func scanFollows(b []byte, pattern string) bool {
 | 
			
		||||
	n := len(pattern)
 | 
			
		||||
 | 
			
		||||
	return len(b) >= n && string(b[:n]) == pattern
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFollowsMultilineBasicStringDelimiter(b []byte) bool {
 | 
			
		||||
	return scanFollows(b, `"""`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFollowsMultilineLiteralStringDelimiter(b []byte) bool {
 | 
			
		||||
	return scanFollows(b, `'''`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFollowsTrue(b []byte) bool {
 | 
			
		||||
	return scanFollows(b, `true`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFollowsFalse(b []byte) bool {
 | 
			
		||||
	return scanFollows(b, `false`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFollowsInf(b []byte) bool {
 | 
			
		||||
	return scanFollows(b, `inf`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanFollowsNan(b []byte) bool {
 | 
			
		||||
	return scanFollows(b, `nan`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanUnquotedKey(b []byte) ([]byte, []byte) {
 | 
			
		||||
	// unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _
 | 
			
		||||
	for i := 0; i < len(b); i++ {
 | 
			
		||||
		if !isUnquotedKeyChar(b[i]) {
 | 
			
		||||
			return b[:i], b[i:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, b[len(b):]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func isUnquotedKeyChar(r byte) bool {
 | 
			
		||||
	return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '_'
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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); {
 | 
			
		||||
		switch b[i] {
 | 
			
		||||
		case '\'':
 | 
			
		||||
			return b[:i+1], b[i+1:], nil
 | 
			
		||||
		case '\n', '\r':
 | 
			
		||||
			return nil, nil, NewParserError(b[i:i+1], "literal strings cannot have new lines")
 | 
			
		||||
		}
 | 
			
		||||
		size := characters.Utf8ValidNext(b[i:])
 | 
			
		||||
		if size == 0 {
 | 
			
		||||
			return nil, nil, NewParserError(b[i:i+1], "invalid character")
 | 
			
		||||
		}
 | 
			
		||||
		i += size
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil, NewParserError(b[len(b):], "unterminated literal string")
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanMultilineLiteralString(b []byte) ([]byte, []byte, error) {
 | 
			
		||||
	// ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body
 | 
			
		||||
	// ml-literal-string-delim
 | 
			
		||||
	// ml-literal-string-delim = 3apostrophe
 | 
			
		||||
	// ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ]
 | 
			
		||||
	//
 | 
			
		||||
	// mll-content = mll-char / newline
 | 
			
		||||
	// mll-char = %x09 / %x20-26 / %x28-7E / non-ascii
 | 
			
		||||
	// mll-quotes = 1*2apostrophe
 | 
			
		||||
	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, NewParserError(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, NewParserError(b[len(b):], `need a \n after \r`)
 | 
			
		||||
			}
 | 
			
		||||
			if b[i+1] != '\n' {
 | 
			
		||||
				return nil, nil, NewParserError(b[i:i+2], `need a \n after \r`)
 | 
			
		||||
			}
 | 
			
		||||
			i += 2 // skip the \n
 | 
			
		||||
			continue
 | 
			
		||||
		}
 | 
			
		||||
		size := characters.Utf8ValidNext(b[i:])
 | 
			
		||||
		if size == 0 {
 | 
			
		||||
			return nil, nil, NewParserError(b[i:i+1], "invalid character")
 | 
			
		||||
		}
 | 
			
		||||
		i += size
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, nil, NewParserError(b[len(b):], `multiline literal string not terminated by '''`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanWindowsNewline(b []byte) ([]byte, []byte, error) {
 | 
			
		||||
	const lenCRLF = 2
 | 
			
		||||
	if len(b) < lenCRLF {
 | 
			
		||||
		return nil, nil, NewParserError(b, "windows new line expected")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if b[1] != '\n' {
 | 
			
		||||
		return nil, nil, NewParserError(b, `windows new line should be \r\n`)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b[:lenCRLF], b[lenCRLF:], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func scanWhitespace(b []byte) ([]byte, []byte) {
 | 
			
		||||
	for i := 0; i < len(b); i++ {
 | 
			
		||||
		switch b[i] {
 | 
			
		||||
		case ' ', '\t':
 | 
			
		||||
			continue
 | 
			
		||||
		default:
 | 
			
		||||
			return b[:i], b[i:]
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, b[len(b):]
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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); {
 | 
			
		||||
		if b[i] == '\n' {
 | 
			
		||||
			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, NewParserError(b[i:i+1], "invalid character in comment")
 | 
			
		||||
		}
 | 
			
		||||
		size := characters.Utf8ValidNext(b[i:])
 | 
			
		||||
		if size == 0 {
 | 
			
		||||
			return nil, nil, NewParserError(b[i:i+1], "invalid character in comment")
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		i += size
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return b, b[len(b):], nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	escaped := false
 | 
			
		||||
	i := 1
 | 
			
		||||
 | 
			
		||||
	for ; i < len(b); i++ {
 | 
			
		||||
		switch b[i] {
 | 
			
		||||
		case '"':
 | 
			
		||||
			return b[:i+1], escaped, b[i+1:], nil
 | 
			
		||||
		case '\n', '\r':
 | 
			
		||||
			return nil, escaped, nil, NewParserError(b[i:i+1], "basic strings cannot have new lines")
 | 
			
		||||
		case '\\':
 | 
			
		||||
			if len(b) < i+2 {
 | 
			
		||||
				return nil, escaped, nil, NewParserError(b[i:i+1], "need a character after \\")
 | 
			
		||||
			}
 | 
			
		||||
			escaped = true
 | 
			
		||||
			i++ // skip the next character
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, escaped, nil, NewParserError(b[len(b):], `basic string not terminated by "`)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
	// ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ]
 | 
			
		||||
	//
 | 
			
		||||
	// mlb-content = mlb-char / newline / mlb-escaped-nl
 | 
			
		||||
	// mlb-char = mlb-unescaped / escaped
 | 
			
		||||
	// mlb-quotes = 1*2quotation-mark
 | 
			
		||||
	// mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii
 | 
			
		||||
	// mlb-escaped-nl = escape ws newline *( wschar / newline )
 | 
			
		||||
 | 
			
		||||
	escaped := false
 | 
			
		||||
	i := 3
 | 
			
		||||
 | 
			
		||||
	for ; i < len(b); i++ {
 | 
			
		||||
		switch b[i] {
 | 
			
		||||
		case '"':
 | 
			
		||||
			if scanFollowsMultilineBasicStringDelimiter(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], 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, NewParserError(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, escaped, nil, NewParserError(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, NewParserError(b[len(b):], `need a \n after \r`)
 | 
			
		||||
			}
 | 
			
		||||
			if b[i+1] != '\n' {
 | 
			
		||||
				return nil, escaped, nil, NewParserError(b[i:i+2], `need a \n after \r`)
 | 
			
		||||
			}
 | 
			
		||||
			i++ // skip the \n
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return nil, escaped, nil, NewParserError(b[len(b):], `multiline basic string not terminated by """`)
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user