mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-29 10:57:44 +09:00 
			
		
		
		
	[Vendor] update go-swagger v0.21.0 -> v0.25.0 (#12670)
* Update go-swagger * vendor
This commit is contained in:
		
							
								
								
									
										22
									
								
								vendor/github.com/pelletier/go-toml/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/pelletier/go-toml/.travis.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,22 +0,0 @@ | ||||
| sudo: false | ||||
| language: go | ||||
| go: | ||||
|   - 1.11.x | ||||
|   - 1.12.x | ||||
|   - tip | ||||
| matrix: | ||||
|   allow_failures: | ||||
|     - go: tip | ||||
|   fast_finish: true | ||||
| env: | ||||
|   - GO111MODULE=on | ||||
| script: | ||||
|   - if [ -n "$(go fmt ./...)" ]; then exit 1; fi | ||||
|   - go test github.com/pelletier/go-toml -race -coverprofile=coverage.txt -covermode=atomic | ||||
|   - go test github.com/pelletier/go-toml/cmd/tomljson | ||||
|   - go test github.com/pelletier/go-toml/cmd/tomll | ||||
|   - go test github.com/pelletier/go-toml/query | ||||
|   - ./benchmark.sh $TRAVIS_BRANCH https://github.com/$TRAVIS_REPO_SLUG.git | ||||
|  | ||||
| after_success: | ||||
|   - bash <(curl -s https://codecov.io/bash) | ||||
							
								
								
									
										1
									
								
								vendor/github.com/pelletier/go-toml/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/pelletier/go-toml/Dockerfile
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -8,3 +8,4 @@ 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 | ||||
|   | ||||
							
								
								
									
										29
									
								
								vendor/github.com/pelletier/go-toml/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								vendor/github.com/pelletier/go-toml/Makefile
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| 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) | ||||
							
								
								
									
										18
									
								
								vendor/github.com/pelletier/go-toml/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										18
									
								
								vendor/github.com/pelletier/go-toml/README.md
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -3,12 +3,11 @@ | ||||
| Go library for the [TOML](https://github.com/mojombo/toml) format. | ||||
|  | ||||
| This library supports TOML version | ||||
| [v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) | ||||
| [v1.0.0-rc.1](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v1.0.0-rc.1.md) | ||||
|  | ||||
| [](http://godoc.org/github.com/pelletier/go-toml) | ||||
| [](https://github.com/pelletier/go-toml/blob/master/LICENSE) | ||||
| [](https://travis-ci.org/pelletier/go-toml) | ||||
| [](https://ci.appveyor.com/project/pelletier/go-toml/branch/master) | ||||
| [](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) | ||||
| @@ -19,7 +18,7 @@ Go-toml provides the following features for using data parsed from TOML document | ||||
|  | ||||
| * Load TOML documents from files and string data | ||||
| * Easily navigate TOML structure using Tree | ||||
| * Mashaling and unmarshaling to and from data structures | ||||
| * 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 | ||||
| @@ -75,7 +74,7 @@ Or use a query: | ||||
| q, _ := query.Compile("$..[user,password]") | ||||
| results := q.Execute(config) | ||||
| for ii, item := range results.Values() { | ||||
|     fmt.Println("Query result %d: %v", ii, item) | ||||
|     fmt.Printf("Query result %d: %v\n", ii, item) | ||||
| } | ||||
| ``` | ||||
|  | ||||
| @@ -88,7 +87,7 @@ The documentation and additional examples are available at | ||||
|  | ||||
| Go-toml provides two handy command line tools: | ||||
|  | ||||
| * `tomll`: Reads TOML files and lint them. | ||||
| * `tomll`: Reads TOML files and lints them. | ||||
|  | ||||
|     ``` | ||||
|     go install github.com/pelletier/go-toml/cmd/tomll | ||||
| @@ -101,6 +100,13 @@ Go-toml provides two handy command line tools: | ||||
|     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 availble as a Docker image from | ||||
|   | ||||
							
								
								
									
										34
									
								
								vendor/github.com/pelletier/go-toml/appveyor.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										34
									
								
								vendor/github.com/pelletier/go-toml/appveyor.yml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,34 +0,0 @@ | ||||
| version: "{build}" | ||||
|  | ||||
| # Source Config | ||||
| clone_folder: c:\gopath\src\github.com\pelletier\go-toml | ||||
|  | ||||
| # Build host | ||||
| environment: | ||||
|   GOPATH: c:\gopath | ||||
|   DEPTESTBYPASS501: 1 | ||||
|   GOVERSION: 1.12 | ||||
|   GO111MODULE: on | ||||
|  | ||||
| init: | ||||
|   - git config --global core.autocrlf input | ||||
|  | ||||
| # Build | ||||
| install: | ||||
|   # Install the specific Go version. | ||||
|   - rmdir c:\go /s /q | ||||
|   - appveyor DownloadFile https://storage.googleapis.com/golang/go%GOVERSION%.windows-amd64.msi | ||||
|   - msiexec /i go%GOVERSION%.windows-amd64.msi /q | ||||
|   - choco install bzr | ||||
|   - set Path=c:\go\bin;c:\gopath\bin;C:\Program Files (x86)\Bazaar\;C:\Program Files\Mercurial\%Path% | ||||
|   - go version | ||||
|   - go env | ||||
|  | ||||
| build: false | ||||
| deploy: false | ||||
|  | ||||
| test_script: | ||||
|   - go test github.com/pelletier/go-toml | ||||
|   - go test github.com/pelletier/go-toml/cmd/tomljson | ||||
|   - go test github.com/pelletier/go-toml/cmd/tomll | ||||
|   - go test github.com/pelletier/go-toml/query | ||||
							
								
								
									
										230
									
								
								vendor/github.com/pelletier/go-toml/azure-pipelines.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										230
									
								
								vendor/github.com/pelletier/go-toml/azure-pipelines.yml
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,230 @@ | ||||
| trigger: | ||||
| - master | ||||
|  | ||||
| stages: | ||||
| - stage: fuzzit | ||||
|   displayName: "Run Fuzzit" | ||||
|   dependsOn: [] | ||||
|   condition: and(succeeded(), eq(variables['Build.SourceBranchName'], 'master')) | ||||
|   jobs: | ||||
|   - job: submit | ||||
|     displayName: "Submit" | ||||
|     pool: | ||||
|       vmImage: ubuntu-latest | ||||
|     steps: | ||||
|     - task: GoTool@0 | ||||
|       displayName: "Install Go 1.14" | ||||
|       inputs: | ||||
|         version: "1.14" | ||||
|     - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" | ||||
|     - script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml | ||||
|     - script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml | ||||
|     - task: Bash@3 | ||||
|       inputs: | ||||
|         filePath: './fuzzit.sh' | ||||
|       env: | ||||
|         TYPE: fuzzing | ||||
|         FUZZIT_API_KEY: $(FUZZIT_API_KEY) | ||||
|  | ||||
| - stage: run_checks | ||||
|   displayName: "Check" | ||||
|   dependsOn: [] | ||||
|   jobs: | ||||
|   - job: fmt | ||||
|     displayName: "fmt" | ||||
|     pool: | ||||
|       vmImage: ubuntu-latest | ||||
|     steps: | ||||
|     - task: GoTool@0 | ||||
|       displayName: "Install Go 1.14" | ||||
|       inputs: | ||||
|         version: "1.14" | ||||
|     - 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.14" | ||||
|       inputs: | ||||
|         version: "1.14" | ||||
|     - 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.14" | ||||
|       inputs: | ||||
|         version: "1.14" | ||||
|     - 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: fuzzing | ||||
|     displayName: "fuzzing" | ||||
|     pool: | ||||
|       vmImage: ubuntu-latest | ||||
|     steps: | ||||
|     - task: GoTool@0 | ||||
|       displayName: "Install Go 1.14" | ||||
|       inputs: | ||||
|         version: "1.14" | ||||
|     - script: echo "##vso[task.setvariable variable=PATH]${PATH}:/home/vsts/go/bin/" | ||||
|     - script: mkdir -p ${HOME}/go/src/github.com/pelletier/go-toml | ||||
|     - script: cp -R . ${HOME}/go/src/github.com/pelletier/go-toml | ||||
|     - task: Bash@3 | ||||
|       inputs: | ||||
|         filePath: './fuzzit.sh' | ||||
|       env: | ||||
|         TYPE: local-regression | ||||
|  | ||||
|   - job: go_unit_tests | ||||
|     displayName: "unit tests" | ||||
|     strategy: | ||||
|       matrix: | ||||
|         linux 1.14: | ||||
|           goVersion: '1.14' | ||||
|           imageName: 'ubuntu-latest' | ||||
|         mac 1.14: | ||||
|           goVersion: '1.14' | ||||
|           imageName: 'macOS-latest' | ||||
|         windows 1.14: | ||||
|           goVersion: '1.14' | ||||
|           imageName: 'windows-latest' | ||||
|         linux 1.13: | ||||
|           goVersion: '1.13' | ||||
|           imageName: 'ubuntu-latest' | ||||
|         mac 1.13: | ||||
|           goVersion: '1.13' | ||||
|           imageName: 'macOS-latest' | ||||
|         windows 1.13: | ||||
|           goVersion: '1.13' | ||||
|           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.14 | ||||
|     - 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' | ||||
							
								
								
									
										5
									
								
								vendor/github.com/pelletier/go-toml/benchmark.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								vendor/github.com/pelletier/go-toml/benchmark.sh
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,6 +1,6 @@ | ||||
| #!/bin/bash | ||||
|  | ||||
| set -e | ||||
| set -ex | ||||
|  | ||||
| reference_ref=${1:-master} | ||||
| reference_git=${2:-.} | ||||
| @@ -8,7 +8,6 @@ reference_git=${2:-.} | ||||
| if ! `hash benchstat 2>/dev/null`; then | ||||
|     echo "Installing benchstat" | ||||
|     go get golang.org/x/perf/cmd/benchstat | ||||
|     go install golang.org/x/perf/cmd/benchstat | ||||
| fi | ||||
|  | ||||
| tempdir=`mktemp -d /tmp/go-toml-benchmark-XXXXXX` | ||||
| @@ -29,4 +28,4 @@ go test -bench=. -benchmem  | tee ${local_benchmark} | ||||
|  | ||||
| echo "" | ||||
| echo "=== diff" | ||||
| benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} | ||||
| benchstat -delta-test=none ${ref_benchmark} ${local_benchmark} | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/github.com/pelletier/go-toml/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/pelletier/go-toml/doc.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| // 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.4.0.md | ||||
| // https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.5.0.md | ||||
| // | ||||
| // Marshaling | ||||
| // | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/pelletier/go-toml/example-crlf.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/pelletier/go-toml/example-crlf.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -27,3 +27,4 @@ enabled = true | ||||
|  | ||||
| [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 | ||||
							
								
								
									
										1
									
								
								vendor/github.com/pelletier/go-toml/example.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/pelletier/go-toml/example.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -27,3 +27,4 @@ enabled = true | ||||
|  | ||||
| [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 | ||||
							
								
								
									
										26
									
								
								vendor/github.com/pelletier/go-toml/fuzzit.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								vendor/github.com/pelletier/go-toml/fuzzit.sh
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| #!/bin/bash | ||||
| set -xe | ||||
|  | ||||
| # go-fuzz doesn't support modules yet, so ensure we do everything | ||||
| # in the old style GOPATH way | ||||
| export GO111MODULE="off" | ||||
|  | ||||
| # install go-fuzz | ||||
| go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build | ||||
|  | ||||
| # target name can only contain lower-case letters (a-z), digits (0-9) and a dash (-) | ||||
| # to add another target, make sure to create it with `fuzzit create target` | ||||
| # before using `fuzzit create job` | ||||
| TARGET=toml-fuzzer | ||||
|  | ||||
| go-fuzz-build -libfuzzer -o ${TARGET}.a github.com/pelletier/go-toml | ||||
| clang -fsanitize=fuzzer ${TARGET}.a -o ${TARGET} | ||||
|  | ||||
| # install fuzzit for talking to fuzzit.dev service | ||||
| # or latest version: | ||||
| # https://github.com/fuzzitdev/fuzzit/releases/latest/download/fuzzit_Linux_x86_64 | ||||
| wget -q -O fuzzit https://github.com/fuzzitdev/fuzzit/releases/download/v2.4.52/fuzzit_Linux_x86_64 | ||||
| chmod a+x fuzzit | ||||
|  | ||||
| # TODO: change kkowalczyk to go-toml and create toml-fuzzer target there | ||||
| ./fuzzit create job --type $TYPE go-toml/${TARGET} ${TARGET} | ||||
							
								
								
									
										2
									
								
								vendor/github.com/pelletier/go-toml/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/github.com/pelletier/go-toml/go.mod
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,5 +5,5 @@ go 1.12 | ||||
| require ( | ||||
| 	github.com/BurntSushi/toml v0.3.1 | ||||
| 	github.com/davecgh/go-spew v1.1.1 | ||||
| 	gopkg.in/yaml.v2 v2.2.2 | ||||
| 	gopkg.in/yaml.v2 v2.3.0 | ||||
| ) | ||||
|   | ||||
							
								
								
									
										12
									
								
								vendor/github.com/pelletier/go-toml/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								vendor/github.com/pelletier/go-toml/go.sum
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,3 +5,15 @@ github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs | ||||
| gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
| gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= | ||||
| gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.3 h1:fvjTMHxHEw/mxHbtzPi3JCcKXQRAnQTBRo6YCJSVHKI= | ||||
| gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= | ||||
| gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c= | ||||
| gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= | ||||
| gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= | ||||
| gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
| gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= | ||||
| gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
|   | ||||
							
								
								
									
										3
									
								
								vendor/github.com/pelletier/go-toml/keysparsing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								vendor/github.com/pelletier/go-toml/keysparsing.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,7 +5,6 @@ package toml | ||||
| import ( | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"unicode" | ||||
| ) | ||||
|  | ||||
| // Convert the bare key group string to an array. | ||||
| @@ -109,5 +108,5 @@ func parseKey(key string) ([]string, error) { | ||||
| } | ||||
|  | ||||
| func isValidBareChar(r rune) bool { | ||||
| 	return isAlphanumeric(r) || r == '-' || unicode.IsNumber(r) | ||||
| 	return isAlphanumeric(r) || r == '-' || isDigit(r) | ||||
| } | ||||
|   | ||||
							
								
								
									
										97
									
								
								vendor/github.com/pelletier/go-toml/lexer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										97
									
								
								vendor/github.com/pelletier/go-toml/lexer.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -26,7 +26,7 @@ type tomlLexer struct { | ||||
| 	currentTokenStart int | ||||
| 	currentTokenStop  int | ||||
| 	tokens            []token | ||||
| 	depth             int | ||||
| 	brackets          []rune | ||||
| 	line              int | ||||
| 	col               int | ||||
| 	endbufferLine     int | ||||
| @@ -123,6 +123,8 @@ func (l *tomlLexer) lexVoid() tomlLexStateFn { | ||||
| 	for { | ||||
| 		next := l.peek() | ||||
| 		switch next { | ||||
| 		case '}': // after '{' | ||||
| 			return l.lexRightCurlyBrace | ||||
| 		case '[': | ||||
| 			return l.lexTableKey | ||||
| 		case '#': | ||||
| @@ -140,10 +142,6 @@ func (l *tomlLexer) lexVoid() tomlLexStateFn { | ||||
| 			l.skip() | ||||
| 		} | ||||
|  | ||||
| 		if l.depth > 0 { | ||||
| 			return l.lexRvalue | ||||
| 		} | ||||
|  | ||||
| 		if isKeyStartChar(next) { | ||||
| 			return l.lexKey | ||||
| 		} | ||||
| @@ -167,10 +165,8 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { | ||||
| 		case '=': | ||||
| 			return l.lexEqual | ||||
| 		case '[': | ||||
| 			l.depth++ | ||||
| 			return l.lexLeftBracket | ||||
| 		case ']': | ||||
| 			l.depth-- | ||||
| 			return l.lexRightBracket | ||||
| 		case '{': | ||||
| 			return l.lexLeftCurlyBrace | ||||
| @@ -188,12 +184,10 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { | ||||
| 			fallthrough | ||||
| 		case '\n': | ||||
| 			l.skip() | ||||
| 			if l.depth == 0 { | ||||
| 				return l.lexVoid | ||||
| 			if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '[' { | ||||
| 				return l.lexRvalue | ||||
| 			} | ||||
| 			return l.lexRvalue | ||||
| 		case '_': | ||||
| 			return l.errorf("cannot start number with underscore") | ||||
| 			return l.lexVoid | ||||
| 		} | ||||
|  | ||||
| 		if l.follow("true") { | ||||
| @@ -223,9 +217,12 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { | ||||
| 		} | ||||
|  | ||||
| 		possibleDate := l.peekString(35) | ||||
| 		dateMatch := dateRegexp.FindString(possibleDate) | ||||
| 		if dateMatch != "" { | ||||
| 			l.fastForward(len(dateMatch)) | ||||
| 		dateSubmatches := dateRegexp.FindStringSubmatch(possibleDate) | ||||
| 		if dateSubmatches != nil && dateSubmatches[0] != "" { | ||||
| 			l.fastForward(len(dateSubmatches[0])) | ||||
| 			if dateSubmatches[2] == "" { // no timezone information => local date | ||||
| 				return l.lexLocalDate | ||||
| 			} | ||||
| 			return l.lexDate | ||||
| 		} | ||||
|  | ||||
| @@ -233,10 +230,6 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { | ||||
| 			return l.lexNumber | ||||
| 		} | ||||
|  | ||||
| 		if isAlphanumeric(next) { | ||||
| 			return l.lexKey | ||||
| 		} | ||||
|  | ||||
| 		return l.errorf("no value can start with %c", next) | ||||
| 	} | ||||
|  | ||||
| @@ -247,12 +240,17 @@ func (l *tomlLexer) lexRvalue() tomlLexStateFn { | ||||
| func (l *tomlLexer) lexLeftCurlyBrace() tomlLexStateFn { | ||||
| 	l.next() | ||||
| 	l.emit(tokenLeftCurlyBrace) | ||||
| 	return l.lexRvalue | ||||
| 	l.brackets = append(l.brackets, '{') | ||||
| 	return l.lexVoid | ||||
| } | ||||
|  | ||||
| func (l *tomlLexer) lexRightCurlyBrace() tomlLexStateFn { | ||||
| 	l.next() | ||||
| 	l.emit(tokenRightCurlyBrace) | ||||
| 	if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '{' { | ||||
| 		return l.errorf("cannot have '}' here") | ||||
| 	} | ||||
| 	l.brackets = l.brackets[:len(l.brackets)-1] | ||||
| 	return l.lexRvalue | ||||
| } | ||||
|  | ||||
| @@ -261,6 +259,11 @@ func (l *tomlLexer) lexDate() tomlLexStateFn { | ||||
| 	return l.lexRvalue | ||||
| } | ||||
|  | ||||
| func (l *tomlLexer) lexLocalDate() tomlLexStateFn { | ||||
| 	l.emit(tokenLocalDate) | ||||
| 	return l.lexRvalue | ||||
| } | ||||
|  | ||||
| func (l *tomlLexer) lexTrue() tomlLexStateFn { | ||||
| 	l.fastForward(4) | ||||
| 	l.emit(tokenTrue) | ||||
| @@ -294,6 +297,9 @@ func (l *tomlLexer) lexEqual() tomlLexStateFn { | ||||
| func (l *tomlLexer) lexComma() tomlLexStateFn { | ||||
| 	l.next() | ||||
| 	l.emit(tokenComma) | ||||
| 	if len(l.brackets) > 0 && l.brackets[len(l.brackets)-1] == '{' { | ||||
| 		return l.lexVoid | ||||
| 	} | ||||
| 	return l.lexRvalue | ||||
| } | ||||
|  | ||||
| @@ -324,7 +330,26 @@ func (l *tomlLexer) lexKey() tomlLexStateFn { | ||||
| 		} else if r == '\n' { | ||||
| 			return l.errorf("keys cannot contain new lines") | ||||
| 		} else if isSpace(r) { | ||||
| 			break | ||||
| 			str := " " | ||||
| 			// skip trailing whitespace | ||||
| 			l.next() | ||||
| 			for r = l.peek(); isSpace(r); r = l.peek() { | ||||
| 				str += string(r) | ||||
| 				l.next() | ||||
| 			} | ||||
| 			// break loop if not a dot | ||||
| 			if r != '.' { | ||||
| 				break | ||||
| 			} | ||||
| 			str += "." | ||||
| 			// skip trailing whitespace after dot | ||||
| 			l.next() | ||||
| 			for r = l.peek(); isSpace(r); r = l.peek() { | ||||
| 				str += string(r) | ||||
| 				l.next() | ||||
| 			} | ||||
| 			growingString += str | ||||
| 			continue | ||||
| 		} else if r == '.' { | ||||
| 			// skip | ||||
| 		} else if !isValidBareChar(r) { | ||||
| @@ -353,6 +378,7 @@ func (l *tomlLexer) lexComment(previousState tomlLexStateFn) tomlLexStateFn { | ||||
| func (l *tomlLexer) lexLeftBracket() tomlLexStateFn { | ||||
| 	l.next() | ||||
| 	l.emit(tokenLeftBracket) | ||||
| 	l.brackets = append(l.brackets, '[') | ||||
| 	return l.lexRvalue | ||||
| } | ||||
|  | ||||
| @@ -504,7 +530,7 @@ func (l *tomlLexer) lexStringAsString(terminator string, discardLeadingNewLine, | ||||
| 		} else { | ||||
| 			r := l.peek() | ||||
|  | ||||
| 			if 0x00 <= r && r <= 0x1F && !(acceptNewLines && (r == '\n' || r == '\r')) { | ||||
| 			if 0x00 <= r && r <= 0x1F && r != '\t' && !(acceptNewLines && (r == '\n' || r == '\r')) { | ||||
| 				return "", fmt.Errorf("unescaped control character %U", r) | ||||
| 			} | ||||
| 			l.next() | ||||
| @@ -535,7 +561,6 @@ func (l *tomlLexer) lexString() tomlLexStateFn { | ||||
| 	} | ||||
|  | ||||
| 	str, err := l.lexStringAsString(terminator, discardLeadingNewLine, acceptNewLines) | ||||
|  | ||||
| 	if err != nil { | ||||
| 		return l.errorf(err.Error()) | ||||
| 	} | ||||
| @@ -607,6 +632,10 @@ func (l *tomlLexer) lexInsideTableKey() tomlLexStateFn { | ||||
| func (l *tomlLexer) lexRightBracket() tomlLexStateFn { | ||||
| 	l.next() | ||||
| 	l.emit(tokenRightBracket) | ||||
| 	if len(l.brackets) == 0 || l.brackets[len(l.brackets)-1] != '[' { | ||||
| 		return l.errorf("cannot have ']' here") | ||||
| 	} | ||||
| 	l.brackets = l.brackets[:len(l.brackets)-1] | ||||
| 	return l.lexRvalue | ||||
| } | ||||
|  | ||||
| @@ -733,7 +762,27 @@ func (l *tomlLexer) run() { | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	dateRegexp = regexp.MustCompile(`^\d{1,4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})`) | ||||
| 	// Regexp for all date/time formats supported by TOML. | ||||
| 	// Group 1: nano precision | ||||
| 	// Group 2: timezone | ||||
| 	// | ||||
| 	// /!\ also matches the empty string | ||||
| 	// | ||||
| 	// Example matches: | ||||
| 	//1979-05-27T07:32:00Z | ||||
| 	//1979-05-27T00:32:00-07:00 | ||||
| 	//1979-05-27T00:32:00.999999-07:00 | ||||
| 	//1979-05-27 07:32:00Z | ||||
| 	//1979-05-27 00:32:00-07:00 | ||||
| 	//1979-05-27 00:32:00.999999-07:00 | ||||
| 	//1979-05-27T07:32:00 | ||||
| 	//1979-05-27T00:32:00.999999 | ||||
| 	//1979-05-27 07:32:00 | ||||
| 	//1979-05-27 00:32:00.999999 | ||||
| 	//1979-05-27 | ||||
| 	//07:32:00 | ||||
| 	//00:32:00.999999 | ||||
| 	dateRegexp = regexp.MustCompile(`^(?:\d{1,4}-\d{2}-\d{2})?(?:[T ]?\d{2}:\d{2}:\d{2}(\.\d{1,9})?(Z|[+-]\d{2}:\d{2})?)?`) | ||||
| } | ||||
|  | ||||
| // Entry point | ||||
|   | ||||
							
								
								
									
										281
									
								
								vendor/github.com/pelletier/go-toml/localtime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										281
									
								
								vendor/github.com/pelletier/go-toml/localtime.go
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,281 @@ | ||||
| // Implementation of TOML's local date/time. | ||||
| // Copied over from https://github.com/googleapis/google-cloud-go/blob/master/civil/civil.go | ||||
| // to avoid pulling all the Google dependencies. | ||||
| // | ||||
| // Copyright 2016 Google LLC | ||||
| // | ||||
| // Licensed under the Apache License, Version 2.0 (the "License"); | ||||
| // you may not use this file except in compliance with the License. | ||||
| // You may obtain a copy of the License at | ||||
| // | ||||
| //      http://www.apache.org/licenses/LICENSE-2.0 | ||||
| // | ||||
| // Unless required by applicable law or agreed to in writing, software | ||||
| // distributed under the License is distributed on an "AS IS" BASIS, | ||||
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
| // See the License for the specific language governing permissions and | ||||
| // limitations under the License. | ||||
|  | ||||
| // Package civil implements types for civil time, a time-zone-independent | ||||
| // representation of time that follows the rules of the proleptic | ||||
| // Gregorian calendar with exactly 24-hour days, 60-minute hours, and 60-second | ||||
| // minutes. | ||||
| // | ||||
| // Because they lack location information, these types do not represent unique | ||||
| // moments or intervals of time. Use time.Time for that purpose. | ||||
| package toml | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"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 | ||||
| } | ||||
							
								
								
									
										669
									
								
								vendor/github.com/pelletier/go-toml/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										669
									
								
								vendor/github.com/pelletier/go-toml/marshal.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -2,6 +2,7 @@ package toml | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"encoding" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| @@ -22,6 +23,7 @@ const ( | ||||
|  | ||||
| type tomlOpts struct { | ||||
| 	name         string | ||||
| 	nameFromTag  bool | ||||
| 	comment      string | ||||
| 	commented    bool | ||||
| 	multiline    bool | ||||
| @@ -68,6 +70,12 @@ const ( | ||||
|  | ||||
| var timeType = reflect.TypeOf(time.Time{}) | ||||
| var marshalerType = reflect.TypeOf(new(Marshaler)).Elem() | ||||
| var unmarshalerType = reflect.TypeOf(new(Unmarshaler)).Elem() | ||||
| var textMarshalerType = reflect.TypeOf(new(encoding.TextMarshaler)).Elem() | ||||
| var textUnmarshalerType = reflect.TypeOf(new(encoding.TextUnmarshaler)).Elem() | ||||
| var localDateType = reflect.TypeOf(LocalDate{}) | ||||
| var localTimeType = reflect.TypeOf(LocalTime{}) | ||||
| var localDateTimeType = reflect.TypeOf(LocalDateTime{}) | ||||
|  | ||||
| // Check if the given marshal type maps to a Tree primitive | ||||
| func isPrimitive(mtype reflect.Type) bool { | ||||
| @@ -85,29 +93,59 @@ func isPrimitive(mtype reflect.Type) bool { | ||||
| 	case reflect.String: | ||||
| 		return true | ||||
| 	case reflect.Struct: | ||||
| 		return mtype == timeType || isCustomMarshaler(mtype) | ||||
| 		return isTimeType(mtype) | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Check if the given marshal type maps to a Tree slice | ||||
| func isTreeSlice(mtype reflect.Type) bool { | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Slice: | ||||
| 		return !isOtherSlice(mtype) | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| func isTimeType(mtype reflect.Type) bool { | ||||
| 	return mtype == timeType || mtype == localDateType || mtype == localDateTimeType || mtype == localTimeType | ||||
| } | ||||
|  | ||||
| // Check if the given marshal type maps to a non-Tree slice | ||||
| func isOtherSlice(mtype reflect.Type) bool { | ||||
| // Check if the given marshal type maps to a Tree slice or array | ||||
| func isTreeSequence(mtype reflect.Type) bool { | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return isOtherSlice(mtype.Elem()) | ||||
| 	case reflect.Slice: | ||||
| 		return isPrimitive(mtype.Elem()) || isOtherSlice(mtype.Elem()) | ||||
| 		return isTreeSequence(mtype.Elem()) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		return isTree(mtype.Elem()) | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Check if the given marshal type maps to a slice or array of a custom marshaler type | ||||
| func isCustomMarshalerSequence(mtype reflect.Type) bool { | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return isCustomMarshalerSequence(mtype.Elem()) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		return isCustomMarshaler(mtype.Elem()) || isCustomMarshaler(reflect.New(mtype.Elem()).Type()) | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Check if the given marshal type maps to a slice or array of a text marshaler type | ||||
| func isTextMarshalerSequence(mtype reflect.Type) bool { | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return isTextMarshalerSequence(mtype.Elem()) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		return isTextMarshaler(mtype.Elem()) || isTextMarshaler(reflect.New(mtype.Elem()).Type()) | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Check if the given marshal type maps to a non-Tree slice or array | ||||
| func isOtherSequence(mtype reflect.Type) bool { | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return isOtherSequence(mtype.Elem()) | ||||
| 	case reflect.Slice, reflect.Array: | ||||
| 		return !isTreeSequence(mtype) | ||||
| 	default: | ||||
| 		return false | ||||
| 	} | ||||
| @@ -116,6 +154,8 @@ func isOtherSlice(mtype reflect.Type) bool { | ||||
| // Check if the given marshal type maps to a Tree | ||||
| func isTree(mtype reflect.Type) bool { | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Ptr: | ||||
| 		return isTree(mtype.Elem()) | ||||
| 	case reflect.Map: | ||||
| 		return true | ||||
| 	case reflect.Struct: | ||||
| @@ -133,12 +173,42 @@ func callCustomMarshaler(mval reflect.Value) ([]byte, error) { | ||||
| 	return mval.Interface().(Marshaler).MarshalTOML() | ||||
| } | ||||
|  | ||||
| func isTextMarshaler(mtype reflect.Type) bool { | ||||
| 	return mtype.Implements(textMarshalerType) && !isTimeType(mtype) | ||||
| } | ||||
|  | ||||
| func callTextMarshaler(mval reflect.Value) ([]byte, error) { | ||||
| 	return mval.Interface().(encoding.TextMarshaler).MarshalText() | ||||
| } | ||||
|  | ||||
| func isCustomUnmarshaler(mtype reflect.Type) bool { | ||||
| 	return mtype.Implements(unmarshalerType) | ||||
| } | ||||
|  | ||||
| func callCustomUnmarshaler(mval reflect.Value, tval interface{}) error { | ||||
| 	return mval.Interface().(Unmarshaler).UnmarshalTOML(tval) | ||||
| } | ||||
|  | ||||
| func isTextUnmarshaler(mtype reflect.Type) bool { | ||||
| 	return mtype.Implements(textUnmarshalerType) | ||||
| } | ||||
|  | ||||
| func callTextUnmarshaler(mval reflect.Value, text []byte) error { | ||||
| 	return mval.Interface().(encoding.TextUnmarshaler).UnmarshalText(text) | ||||
| } | ||||
|  | ||||
| // Marshaler is the interface implemented by types that | ||||
| // can marshal themselves into valid TOML. | ||||
| type Marshaler interface { | ||||
| 	MarshalTOML() ([]byte, error) | ||||
| } | ||||
|  | ||||
| // Unmarshaler is the interface implemented by types that | ||||
| // can unmarshal a TOML description of themselves. | ||||
| type Unmarshaler interface { | ||||
| 	UnmarshalTOML(interface{}) error | ||||
| } | ||||
|  | ||||
| /* | ||||
| Marshal returns the TOML encoding of v.  Behavior is similar to the Go json | ||||
| encoder, except that there is no concept of a Marshaler interface or MarshalTOML | ||||
| @@ -170,7 +240,7 @@ Tree primitive types and corresponding marshal types: | ||||
|   float64    float32, float64, pointers to same | ||||
|   string     string, pointers to same | ||||
|   bool       bool, pointers to same | ||||
|   time.Time  time.Time{}, pointers to same | ||||
|   time.LocalTime  time.LocalTime{}, pointers to same | ||||
|  | ||||
| For additional flexibility, use the Encoder API. | ||||
| */ | ||||
| @@ -183,20 +253,23 @@ type Encoder struct { | ||||
| 	w io.Writer | ||||
| 	encOpts | ||||
| 	annotation | ||||
| 	line  int | ||||
| 	col   int | ||||
| 	order marshalOrder | ||||
| 	line        int | ||||
| 	col         int | ||||
| 	order       marshalOrder | ||||
| 	promoteAnon bool | ||||
| 	indentation string | ||||
| } | ||||
|  | ||||
| // NewEncoder returns a new encoder that writes to w. | ||||
| func NewEncoder(w io.Writer) *Encoder { | ||||
| 	return &Encoder{ | ||||
| 		w:          w, | ||||
| 		encOpts:    encOptsDefaults, | ||||
| 		annotation: annotationDefault, | ||||
| 		line:       0, | ||||
| 		col:        1, | ||||
| 		order:      OrderAlphabetical, | ||||
| 		w:           w, | ||||
| 		encOpts:     encOptsDefaults, | ||||
| 		annotation:  annotationDefault, | ||||
| 		line:        0, | ||||
| 		col:         1, | ||||
| 		order:       OrderAlphabetical, | ||||
| 		indentation: "  ", | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -248,6 +321,12 @@ func (e *Encoder) Order(ord marshalOrder) *Encoder { | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // Indentation allows to change indentation when marshalling. | ||||
| func (e *Encoder) Indentation(indent string) *Encoder { | ||||
| 	e.indentation = indent | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // SetTagName allows changing default tag "toml" | ||||
| func (e *Encoder) SetTagName(v string) *Encoder { | ||||
| 	e.tag = v | ||||
| @@ -272,8 +351,31 @@ func (e *Encoder) SetTagMultiline(v string) *Encoder { | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| // PromoteAnonymous allows to change how anonymous struct fields are marshaled. | ||||
| // Usually, they are marshaled as if the inner exported fields were fields in | ||||
| // the outer struct. However, if an anonymous struct field is given a name in | ||||
| // its TOML tag, it is treated like a regular struct field with that name. | ||||
| // rather than being anonymous. | ||||
| // | ||||
| // In case anonymous promotion is enabled, all anonymous structs are promoted | ||||
| // and treated like regular struct fields. | ||||
| func (e *Encoder) PromoteAnonymous(promote bool) *Encoder { | ||||
| 	e.promoteAnon = promote | ||||
| 	return e | ||||
| } | ||||
|  | ||||
| func (e *Encoder) marshal(v interface{}) ([]byte, error) { | ||||
| 	// Check if indentation is valid | ||||
| 	for _, char := range e.indentation { | ||||
| 		if !isSpace(char) { | ||||
| 			return []byte{}, fmt.Errorf("invalid indentation: must only contains space or tab characters") | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	mtype := reflect.TypeOf(v) | ||||
| 	if mtype == nil { | ||||
| 		return []byte{}, errors.New("nil cannot be marshaled to TOML") | ||||
| 	} | ||||
|  | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Struct, reflect.Map: | ||||
| @@ -281,6 +383,9 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) { | ||||
| 		if mtype.Elem().Kind() != reflect.Struct { | ||||
| 			return []byte{}, errors.New("Only pointer to struct can be marshaled to TOML") | ||||
| 		} | ||||
| 		if reflect.ValueOf(v).IsNil() { | ||||
| 			return []byte{}, errors.New("nil pointer cannot be marshaled to TOML") | ||||
| 		} | ||||
| 	default: | ||||
| 		return []byte{}, errors.New("Only a struct or map can be marshaled to TOML") | ||||
| 	} | ||||
| @@ -289,13 +394,16 @@ func (e *Encoder) marshal(v interface{}) ([]byte, error) { | ||||
| 	if isCustomMarshaler(mtype) { | ||||
| 		return callCustomMarshaler(sval) | ||||
| 	} | ||||
| 	if isTextMarshaler(mtype) { | ||||
| 		return callTextMarshaler(sval) | ||||
| 	} | ||||
| 	t, err := e.valueToTree(mtype, sval) | ||||
| 	if err != nil { | ||||
| 		return []byte{}, err | ||||
| 	} | ||||
|  | ||||
| 	var buf bytes.Buffer | ||||
| 	_, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order) | ||||
| 	_, err = t.writeToOrdered(&buf, "", "", 0, e.arraysOneElementPerLine, e.order, e.indentation, false) | ||||
|  | ||||
| 	return buf.Bytes(), err | ||||
| } | ||||
| @@ -313,20 +421,28 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er | ||||
| 	tval := e.nextTree() | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Struct: | ||||
| 		for i := 0; i < mtype.NumField(); i++ { | ||||
| 			mtypef, mvalf := mtype.Field(i), mval.Field(i) | ||||
| 			opts := tomlOptions(mtypef, e.annotation) | ||||
| 			if opts.include && (!opts.omitempty || !isZero(mvalf)) { | ||||
| 				val, err := e.valueToToml(mtypef.Type, mvalf) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 		switch mval.Interface().(type) { | ||||
| 		case Tree: | ||||
| 			reflect.ValueOf(tval).Elem().Set(mval) | ||||
| 		default: | ||||
| 			for i := 0; i < mtype.NumField(); i++ { | ||||
| 				mtypef, mvalf := mtype.Field(i), mval.Field(i) | ||||
| 				opts := tomlOptions(mtypef, e.annotation) | ||||
| 				if opts.include && ((mtypef.Type.Kind() != reflect.Interface && !opts.omitempty) || !isZero(mvalf)) { | ||||
| 					val, err := e.valueToToml(mtypef.Type, mvalf) | ||||
| 					if err != nil { | ||||
| 						return nil, err | ||||
| 					} | ||||
| 					if tree, ok := val.(*Tree); ok && mtypef.Anonymous && !opts.nameFromTag && !e.promoteAnon { | ||||
| 						e.appendTree(tval, tree) | ||||
| 					} else { | ||||
| 						tval.SetPathWithOptions([]string{opts.name}, SetOptions{ | ||||
| 							Comment:   opts.comment, | ||||
| 							Commented: opts.commented, | ||||
| 							Multiline: opts.multiline, | ||||
| 						}, val) | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				tval.SetWithOptions(opts.name, SetOptions{ | ||||
| 					Comment:   opts.comment, | ||||
| 					Commented: opts.commented, | ||||
| 					Multiline: opts.multiline, | ||||
| 				}, val) | ||||
| 			} | ||||
| 		} | ||||
| 	case reflect.Map: | ||||
| @@ -351,18 +467,21 @@ func (e *Encoder) valueToTree(mtype reflect.Type, mval reflect.Value) (*Tree, er | ||||
| 		} | ||||
| 		for _, key := range keys { | ||||
| 			mvalf := mval.MapIndex(key) | ||||
| 			if (mtype.Elem().Kind() == reflect.Ptr || mtype.Elem().Kind() == reflect.Interface) && mvalf.IsNil() { | ||||
| 				continue | ||||
| 			} | ||||
| 			val, err := e.valueToToml(mtype.Elem(), mvalf) | ||||
| 			if err != nil { | ||||
| 				return nil, err | ||||
| 			} | ||||
| 			if e.quoteMapKeys { | ||||
| 				keyStr, err := tomlValueStringRepresentation(key.String(), "", e.arraysOneElementPerLine) | ||||
| 				keyStr, err := tomlValueStringRepresentation(key.String(), "", "", e.order, e.arraysOneElementPerLine) | ||||
| 				if err != nil { | ||||
| 					return nil, err | ||||
| 				} | ||||
| 				tval.SetPath([]string{keyStr}, val) | ||||
| 			} else { | ||||
| 				tval.Set(key.String(), val) | ||||
| 				tval.SetPath([]string{key.String()}, val) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| @@ -399,17 +518,29 @@ func (e *Encoder) valueToOtherSlice(mtype reflect.Type, mval reflect.Value) (int | ||||
| func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface{}, error) { | ||||
| 	e.line++ | ||||
| 	if mtype.Kind() == reflect.Ptr { | ||||
| 		return e.valueToToml(mtype.Elem(), mval.Elem()) | ||||
| 		switch { | ||||
| 		case isCustomMarshaler(mtype): | ||||
| 			return callCustomMarshaler(mval) | ||||
| 		case isTextMarshaler(mtype): | ||||
| 			return callTextMarshaler(mval) | ||||
| 		default: | ||||
| 			return e.valueToToml(mtype.Elem(), mval.Elem()) | ||||
| 		} | ||||
| 	} | ||||
| 	if mtype.Kind() == reflect.Interface { | ||||
| 		return e.valueToToml(mval.Elem().Type(), mval.Elem()) | ||||
| 	} | ||||
| 	switch { | ||||
| 	case isCustomMarshaler(mtype): | ||||
| 		return callCustomMarshaler(mval) | ||||
| 	case isTextMarshaler(mtype): | ||||
| 		return callTextMarshaler(mval) | ||||
| 	case isTree(mtype): | ||||
| 		return e.valueToTree(mtype, mval) | ||||
| 	case isTreeSlice(mtype): | ||||
| 		return e.valueToTreeSlice(mtype, mval) | ||||
| 	case isOtherSlice(mtype): | ||||
| 	case isOtherSequence(mtype), isCustomMarshalerSequence(mtype), isTextMarshalerSequence(mtype): | ||||
| 		return e.valueToOtherSlice(mtype, mval) | ||||
| 	case isTreeSequence(mtype): | ||||
| 		return e.valueToTreeSlice(mtype, mval) | ||||
| 	default: | ||||
| 		switch mtype.Kind() { | ||||
| 		case reflect.Bool: | ||||
| @@ -426,13 +557,26 @@ func (e *Encoder) valueToToml(mtype reflect.Type, mval reflect.Value) (interface | ||||
| 		case reflect.String: | ||||
| 			return mval.String(), nil | ||||
| 		case reflect.Struct: | ||||
| 			return mval.Interface().(time.Time), nil | ||||
| 			return mval.Interface(), nil | ||||
| 		default: | ||||
| 			return nil, fmt.Errorf("Marshal can't handle %v(%v)", mtype, mtype.Kind()) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (e *Encoder) appendTree(t, o *Tree) error { | ||||
| 	for key, value := range o.values { | ||||
| 		if _, ok := t.values[key]; ok { | ||||
| 			continue | ||||
| 		} | ||||
| 		if tomlValue, ok := value.(*tomlValue); ok { | ||||
| 			tomlValue.position.Col = t.position.Col | ||||
| 		} | ||||
| 		t.values[key] = value | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Unmarshal attempts to unmarshal the Tree into a Go struct pointed by v. | ||||
| // Neither Unmarshaler interfaces nor UnmarshalTOML functions are supported for | ||||
| // sub-structs, and only definite types can be unmarshaled. | ||||
| @@ -445,8 +589,11 @@ func (t *Tree) Unmarshal(v interface{}) error { | ||||
| // See Marshal() documentation for types mapping table. | ||||
| func (t *Tree) Marshal() ([]byte, error) { | ||||
| 	var buf bytes.Buffer | ||||
| 	err := NewEncoder(&buf).Encode(t) | ||||
| 	return buf.Bytes(), err | ||||
| 	_, err := t.WriteTo(&buf) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return buf.Bytes(), nil | ||||
| } | ||||
|  | ||||
| // Unmarshal parses the TOML-encoded data and stores the result in the value | ||||
| @@ -482,6 +629,8 @@ type Decoder struct { | ||||
| 	tval *Tree | ||||
| 	encOpts | ||||
| 	tagName string | ||||
| 	strict  bool | ||||
| 	visitor visitorState | ||||
| } | ||||
|  | ||||
| // NewDecoder returns a new decoder that reads from r. | ||||
| @@ -512,8 +661,18 @@ func (d *Decoder) SetTagName(v string) *Decoder { | ||||
| 	return d | ||||
| } | ||||
|  | ||||
| // Strict allows changing to strict decoding. Any fields that are found in the | ||||
| // input data and do not have a corresponding struct member cause an error. | ||||
| func (d *Decoder) Strict(strict bool) *Decoder { | ||||
| 	d.strict = strict | ||||
| 	return d | ||||
| } | ||||
|  | ||||
| func (d *Decoder) unmarshal(v interface{}) error { | ||||
| 	mtype := reflect.TypeOf(v) | ||||
| 	if mtype == nil { | ||||
| 		return errors.New("nil cannot be unmarshaled from TOML") | ||||
| 	} | ||||
| 	if mtype.Kind() != reflect.Ptr { | ||||
| 		return errors.New("only a pointer to struct or map can be unmarshaled from TOML") | ||||
| 	} | ||||
| @@ -526,28 +685,64 @@ func (d *Decoder) unmarshal(v interface{}) error { | ||||
| 		return errors.New("only a pointer to struct or map can be unmarshaled from TOML") | ||||
| 	} | ||||
|  | ||||
| 	sval, err := d.valueFromTree(elem, d.tval) | ||||
| 	if reflect.ValueOf(v).IsNil() { | ||||
| 		return errors.New("nil pointer cannot be unmarshaled from TOML") | ||||
| 	} | ||||
|  | ||||
| 	vv := reflect.ValueOf(v).Elem() | ||||
|  | ||||
| 	if d.strict { | ||||
| 		d.visitor = newVisitorState(d.tval) | ||||
| 	} | ||||
|  | ||||
| 	sval, err := d.valueFromTree(elem, d.tval, &vv) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if err := d.visitor.validate(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	reflect.ValueOf(v).Elem().Set(sval) | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // Convert toml tree to marshal struct or map, using marshal type | ||||
| func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, error) { | ||||
| // Convert toml tree to marshal struct or map, using marshal type. When mval1 | ||||
| // is non-nil, merge fields into the given value instead of allocating a new one. | ||||
| func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree, mval1 *reflect.Value) (reflect.Value, error) { | ||||
| 	if mtype.Kind() == reflect.Ptr { | ||||
| 		return d.unwrapPointer(mtype, tval) | ||||
| 		return d.unwrapPointer(mtype, tval, mval1) | ||||
| 	} | ||||
|  | ||||
| 	// Check if pointer to value implements the Unmarshaler interface. | ||||
| 	if mvalPtr := reflect.New(mtype); isCustomUnmarshaler(mvalPtr.Type()) { | ||||
| 		d.visitor.visitAll() | ||||
|  | ||||
| 		if err := callCustomUnmarshaler(mvalPtr, tval.ToMap()); err != nil { | ||||
| 			return reflect.ValueOf(nil), fmt.Errorf("unmarshal toml: %v", err) | ||||
| 		} | ||||
| 		return mvalPtr.Elem(), nil | ||||
| 	} | ||||
|  | ||||
| 	var mval reflect.Value | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Struct: | ||||
| 		mval = reflect.New(mtype).Elem() | ||||
| 		for i := 0; i < mtype.NumField(); i++ { | ||||
| 			mtypef := mtype.Field(i) | ||||
| 			an := annotation{tag: d.tagName} | ||||
| 			opts := tomlOptions(mtypef, an) | ||||
| 			if opts.include { | ||||
| 		if mval1 != nil { | ||||
| 			mval = *mval1 | ||||
| 		} else { | ||||
| 			mval = reflect.New(mtype).Elem() | ||||
| 		} | ||||
|  | ||||
| 		switch mval.Interface().(type) { | ||||
| 		case Tree: | ||||
| 			mval.Set(reflect.ValueOf(tval).Elem()) | ||||
| 		default: | ||||
| 			for i := 0; i < mtype.NumField(); i++ { | ||||
| 				mtypef := mtype.Field(i) | ||||
| 				an := annotation{tag: d.tagName} | ||||
| 				opts := tomlOptions(mtypef, an) | ||||
| 				if !opts.include { | ||||
| 					continue | ||||
| 				} | ||||
| 				baseKey := opts.name | ||||
| 				keysToTry := []string{ | ||||
| 					baseKey, | ||||
| @@ -557,19 +752,25 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, | ||||
| 				} | ||||
|  | ||||
| 				found := false | ||||
| 				for _, key := range keysToTry { | ||||
| 					exists := tval.Has(key) | ||||
| 					if !exists { | ||||
| 						continue | ||||
| 				if tval != nil { | ||||
| 					for _, key := range keysToTry { | ||||
| 						exists := tval.HasPath([]string{key}) | ||||
| 						if !exists { | ||||
| 							continue | ||||
| 						} | ||||
|  | ||||
| 						d.visitor.push(key) | ||||
| 						val := tval.GetPath([]string{key}) | ||||
| 						fval := mval.Field(i) | ||||
| 						mvalf, err := d.valueFromToml(mtypef.Type, val, &fval) | ||||
| 						if err != nil { | ||||
| 							return mval, formatError(err, tval.GetPositionPath([]string{key})) | ||||
| 						} | ||||
| 						mval.Field(i).Set(mvalf) | ||||
| 						found = true | ||||
| 						d.visitor.pop() | ||||
| 						break | ||||
| 					} | ||||
| 					val := tval.Get(key) | ||||
| 					mvalf, err := d.valueFromToml(mtypef.Type, val) | ||||
| 					if err != nil { | ||||
| 						return mval, formatError(err, tval.GetPosition(key)) | ||||
| 					} | ||||
| 					mval.Field(i).Set(mvalf) | ||||
| 					found = true | ||||
| 					break | ||||
| 				} | ||||
|  | ||||
| 				if !found && opts.defaultValue != "" { | ||||
| @@ -577,45 +778,71 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, | ||||
| 					var val interface{} | ||||
| 					var err error | ||||
| 					switch mvalf.Kind() { | ||||
| 					case reflect.Bool: | ||||
| 						val, err = strconv.ParseBool(opts.defaultValue) | ||||
| 						if err != nil { | ||||
| 							return mval.Field(i), err | ||||
| 						} | ||||
| 					case reflect.Int: | ||||
| 						val, err = strconv.Atoi(opts.defaultValue) | ||||
| 						if err != nil { | ||||
| 							return mval.Field(i), err | ||||
| 						} | ||||
| 					case reflect.String: | ||||
| 						val = opts.defaultValue | ||||
| 					case reflect.Bool: | ||||
| 						val, err = strconv.ParseBool(opts.defaultValue) | ||||
| 					case reflect.Uint: | ||||
| 						val, err = strconv.ParseUint(opts.defaultValue, 10, 0) | ||||
| 					case reflect.Uint8: | ||||
| 						val, err = strconv.ParseUint(opts.defaultValue, 10, 8) | ||||
| 					case reflect.Uint16: | ||||
| 						val, err = strconv.ParseUint(opts.defaultValue, 10, 16) | ||||
| 					case reflect.Uint32: | ||||
| 						val, err = strconv.ParseUint(opts.defaultValue, 10, 32) | ||||
| 					case reflect.Uint64: | ||||
| 						val, err = strconv.ParseUint(opts.defaultValue, 10, 64) | ||||
| 					case reflect.Int: | ||||
| 						val, err = strconv.ParseInt(opts.defaultValue, 10, 0) | ||||
| 					case reflect.Int8: | ||||
| 						val, err = strconv.ParseInt(opts.defaultValue, 10, 8) | ||||
| 					case reflect.Int16: | ||||
| 						val, err = strconv.ParseInt(opts.defaultValue, 10, 16) | ||||
| 					case reflect.Int32: | ||||
| 						val, err = strconv.ParseInt(opts.defaultValue, 10, 32) | ||||
| 					case reflect.Int64: | ||||
| 						val, err = strconv.ParseInt(opts.defaultValue, 10, 64) | ||||
| 						if err != nil { | ||||
| 							return mval.Field(i), err | ||||
| 						} | ||||
| 					case reflect.Float32: | ||||
| 						val, err = strconv.ParseFloat(opts.defaultValue, 32) | ||||
| 					case reflect.Float64: | ||||
| 						val, err = strconv.ParseFloat(opts.defaultValue, 64) | ||||
| 						if err != nil { | ||||
| 							return mval.Field(i), err | ||||
| 						} | ||||
| 					default: | ||||
| 						return mval.Field(i), fmt.Errorf("unsuported field type for default option") | ||||
| 						return mvalf, fmt.Errorf("unsupported field type for default option") | ||||
| 					} | ||||
| 					mval.Field(i).Set(reflect.ValueOf(val)) | ||||
|  | ||||
| 					if err != nil { | ||||
| 						return mvalf, err | ||||
| 					} | ||||
| 					mvalf.Set(reflect.ValueOf(val).Convert(mvalf.Type())) | ||||
| 				} | ||||
|  | ||||
| 				// save the old behavior above and try to check structs | ||||
| 				if !found && opts.defaultValue == "" && mtypef.Type.Kind() == reflect.Struct { | ||||
| 					tmpTval := tval | ||||
| 					if !mtypef.Anonymous { | ||||
| 						tmpTval = nil | ||||
| 					} | ||||
| 					fval := mval.Field(i) | ||||
| 					v, err := d.valueFromTree(mtypef.Type, tmpTval, &fval) | ||||
| 					if err != nil { | ||||
| 						return v, err | ||||
| 					} | ||||
| 					mval.Field(i).Set(v) | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	case reflect.Map: | ||||
| 		mval = reflect.MakeMap(mtype) | ||||
| 		for _, key := range tval.Keys() { | ||||
| 			d.visitor.push(key) | ||||
| 			// TODO: path splits key | ||||
| 			val := tval.GetPath([]string{key}) | ||||
| 			mvalf, err := d.valueFromToml(mtype.Elem(), val) | ||||
| 			mvalf, err := d.valueFromToml(mtype.Elem(), val, nil) | ||||
| 			if err != nil { | ||||
| 				return mval, formatError(err, tval.GetPosition(key)) | ||||
| 				return mval, formatError(err, tval.GetPositionPath([]string{key})) | ||||
| 			} | ||||
| 			mval.SetMapIndex(reflect.ValueOf(key).Convert(mtype.Key()), mvalf) | ||||
| 			d.visitor.pop() | ||||
| 		} | ||||
| 	} | ||||
| 	return mval, nil | ||||
| @@ -623,9 +850,32 @@ func (d *Decoder) valueFromTree(mtype reflect.Type, tval *Tree) (reflect.Value, | ||||
|  | ||||
| // Convert toml value to marshal struct/map slice, using marshal type | ||||
| func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect.Value, error) { | ||||
| 	mval := reflect.MakeSlice(mtype, len(tval), len(tval)) | ||||
| 	mval, err := makeSliceOrArray(mtype, len(tval)) | ||||
| 	if err != nil { | ||||
| 		return mval, err | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < len(tval); i++ { | ||||
| 		val, err := d.valueFromTree(mtype.Elem(), tval[i]) | ||||
| 		d.visitor.push(strconv.Itoa(i)) | ||||
| 		val, err := d.valueFromTree(mtype.Elem(), tval[i], nil) | ||||
| 		if err != nil { | ||||
| 			return mval, err | ||||
| 		} | ||||
| 		mval.Index(i).Set(val) | ||||
| 		d.visitor.pop() | ||||
| 	} | ||||
| 	return mval, nil | ||||
| } | ||||
|  | ||||
| // Convert toml value to marshal primitive slice, using marshal type | ||||
| func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { | ||||
| 	mval, err := makeSliceOrArray(mtype, len(tval)) | ||||
| 	if err != nil { | ||||
| 		return mval, err | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < len(tval); i++ { | ||||
| 		val, err := d.valueFromToml(mtype.Elem(), tval[i], nil) | ||||
| 		if err != nil { | ||||
| 			return mval, err | ||||
| 		} | ||||
| @@ -635,10 +885,17 @@ func (d *Decoder) valueFromTreeSlice(mtype reflect.Type, tval []*Tree) (reflect. | ||||
| } | ||||
|  | ||||
| // Convert toml value to marshal primitive slice, using marshal type | ||||
| func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (reflect.Value, error) { | ||||
| 	mval := reflect.MakeSlice(mtype, len(tval), len(tval)) | ||||
| 	for i := 0; i < len(tval); i++ { | ||||
| 		val, err := d.valueFromToml(mtype.Elem(), tval[i]) | ||||
| func (d *Decoder) valueFromOtherSliceI(mtype reflect.Type, tval interface{}) (reflect.Value, error) { | ||||
| 	val := reflect.ValueOf(tval) | ||||
| 	length := val.Len() | ||||
|  | ||||
| 	mval, err := makeSliceOrArray(mtype, length) | ||||
| 	if err != nil { | ||||
| 		return mval, err | ||||
| 	} | ||||
|  | ||||
| 	for i := 0; i < length; i++ { | ||||
| 		val, err := d.valueFromToml(mtype.Elem(), val.Index(i).Interface(), nil) | ||||
| 		if err != nil { | ||||
| 			return mval, err | ||||
| 		} | ||||
| @@ -647,33 +904,113 @@ func (d *Decoder) valueFromOtherSlice(mtype reflect.Type, tval []interface{}) (r | ||||
| 	return mval, nil | ||||
| } | ||||
|  | ||||
| // Convert toml value to marshal value, using marshal type | ||||
| func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.Value, error) { | ||||
| // Create a new slice or a new array with specified length | ||||
| func makeSliceOrArray(mtype reflect.Type, tLength int) (reflect.Value, error) { | ||||
| 	var mval reflect.Value | ||||
| 	switch mtype.Kind() { | ||||
| 	case reflect.Slice: | ||||
| 		mval = reflect.MakeSlice(mtype, tLength, tLength) | ||||
| 	case reflect.Array: | ||||
| 		mval = reflect.New(reflect.ArrayOf(mtype.Len(), mtype.Elem())).Elem() | ||||
| 		if tLength > mtype.Len() { | ||||
| 			return mval, fmt.Errorf("unmarshal: TOML array length (%v) exceeds destination array length (%v)", tLength, mtype.Len()) | ||||
| 		} | ||||
| 	} | ||||
| 	return mval, nil | ||||
| } | ||||
|  | ||||
| // Convert toml value to marshal value, using marshal type. When mval1 is non-nil | ||||
| // and the given type is a struct value, merge fields into it. | ||||
| func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { | ||||
| 	if mtype.Kind() == reflect.Ptr { | ||||
| 		return d.unwrapPointer(mtype, tval) | ||||
| 		return d.unwrapPointer(mtype, tval, mval1) | ||||
| 	} | ||||
|  | ||||
| 	switch t := tval.(type) { | ||||
| 	case *Tree: | ||||
| 		if isTree(mtype) { | ||||
| 			return d.valueFromTree(mtype, t) | ||||
| 		var mval11 *reflect.Value | ||||
| 		if mtype.Kind() == reflect.Struct { | ||||
| 			mval11 = mval1 | ||||
| 		} | ||||
|  | ||||
| 		if isTree(mtype) { | ||||
| 			return d.valueFromTree(mtype, t, mval11) | ||||
| 		} | ||||
|  | ||||
| 		if mtype.Kind() == reflect.Interface { | ||||
| 			if mval1 == nil || mval1.IsNil() { | ||||
| 				return d.valueFromTree(reflect.TypeOf(map[string]interface{}{}), t, nil) | ||||
| 			} else { | ||||
| 				return d.valueFromToml(mval1.Elem().Type(), t, nil) | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a tree", tval, tval) | ||||
| 	case []*Tree: | ||||
| 		if isTreeSlice(mtype) { | ||||
| 		if isTreeSequence(mtype) { | ||||
| 			return d.valueFromTreeSlice(mtype, t) | ||||
| 		} | ||||
| 		if mtype.Kind() == reflect.Interface { | ||||
| 			if mval1 == nil || mval1.IsNil() { | ||||
| 				return d.valueFromTreeSlice(reflect.TypeOf([]map[string]interface{}{}), t) | ||||
| 			} else { | ||||
| 				ival := mval1.Elem() | ||||
| 				return d.valueFromToml(mval1.Elem().Type(), t, &ival) | ||||
| 			} | ||||
| 		} | ||||
| 		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to trees", tval, tval) | ||||
| 	case []interface{}: | ||||
| 		if isOtherSlice(mtype) { | ||||
| 		d.visitor.visit() | ||||
| 		if isOtherSequence(mtype) { | ||||
| 			return d.valueFromOtherSlice(mtype, t) | ||||
| 		} | ||||
| 		if mtype.Kind() == reflect.Interface { | ||||
| 			if mval1 == nil || mval1.IsNil() { | ||||
| 				return d.valueFromOtherSlice(reflect.TypeOf([]interface{}{}), t) | ||||
| 			} else { | ||||
| 				ival := mval1.Elem() | ||||
| 				return d.valueFromToml(mval1.Elem().Type(), t, &ival) | ||||
| 			} | ||||
| 		} | ||||
| 		return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to a slice", tval, tval) | ||||
| 	default: | ||||
| 		d.visitor.visit() | ||||
| 		// Check if pointer to value implements the encoding.TextUnmarshaler. | ||||
| 		if mvalPtr := reflect.New(mtype); isTextUnmarshaler(mvalPtr.Type()) && !isTimeType(mtype) { | ||||
| 			if err := d.unmarshalText(tval, mvalPtr); err != nil { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("unmarshal text: %v", err) | ||||
| 			} | ||||
| 			return mvalPtr.Elem(), nil | ||||
| 		} | ||||
|  | ||||
| 		switch mtype.Kind() { | ||||
| 		case reflect.Bool, reflect.Struct: | ||||
| 			val := reflect.ValueOf(tval) | ||||
| 			// if this passes for when mtype is reflect.Struct, tval is a time.Time | ||||
|  | ||||
| 			switch val.Type() { | ||||
| 			case localDateType: | ||||
| 				localDate := val.Interface().(LocalDate) | ||||
| 				switch mtype { | ||||
| 				case timeType: | ||||
| 					return reflect.ValueOf(time.Date(localDate.Year, localDate.Month, localDate.Day, 0, 0, 0, 0, time.Local)), nil | ||||
| 				} | ||||
| 			case localDateTimeType: | ||||
| 				localDateTime := val.Interface().(LocalDateTime) | ||||
| 				switch mtype { | ||||
| 				case timeType: | ||||
| 					return reflect.ValueOf(time.Date( | ||||
| 						localDateTime.Date.Year, | ||||
| 						localDateTime.Date.Month, | ||||
| 						localDateTime.Date.Day, | ||||
| 						localDateTime.Time.Hour, | ||||
| 						localDateTime.Time.Minute, | ||||
| 						localDateTime.Time.Second, | ||||
| 						localDateTime.Time.Nanosecond, | ||||
| 						time.Local)), nil | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			// if this passes for when mtype is reflect.Struct, tval is a time.LocalTime | ||||
| 			if !val.Type().ConvertibleTo(mtype) { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
| @@ -696,46 +1033,65 @@ func (d *Decoder) valueFromToml(mtype reflect.Type, tval interface{}) (reflect.V | ||||
| 				} | ||||
| 				return reflect.ValueOf(d), nil | ||||
| 			} | ||||
| 			if !val.Type().ConvertibleTo(mtype) { | ||||
| 			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
| 			if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(mtype).Int()) { | ||||
| 			if reflect.Indirect(reflect.New(mtype)).OverflowInt(val.Convert(reflect.TypeOf(int64(0))).Int()) { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
|  | ||||
| 			return val.Convert(mtype), nil | ||||
| 		case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: | ||||
| 			val := reflect.ValueOf(tval) | ||||
| 			if !val.Type().ConvertibleTo(mtype) { | ||||
| 			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Float64 { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
|  | ||||
| 			if val.Convert(reflect.TypeOf(int(1))).Int() < 0 { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) is negative so does not fit in %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
| 			if reflect.Indirect(reflect.New(mtype)).OverflowUint(uint64(val.Convert(mtype).Uint())) { | ||||
| 			if reflect.Indirect(reflect.New(mtype)).OverflowUint(val.Convert(reflect.TypeOf(uint64(0))).Uint()) { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
|  | ||||
| 			return val.Convert(mtype), nil | ||||
| 		case reflect.Float32, reflect.Float64: | ||||
| 			val := reflect.ValueOf(tval) | ||||
| 			if !val.Type().ConvertibleTo(mtype) { | ||||
| 			if !val.Type().ConvertibleTo(mtype) || val.Kind() == reflect.Int64 { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
| 			if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(mtype).Float()) { | ||||
| 			if reflect.Indirect(reflect.New(mtype)).OverflowFloat(val.Convert(reflect.TypeOf(float64(0))).Float()) { | ||||
| 				return reflect.ValueOf(nil), fmt.Errorf("%v(%T) would overflow %v", tval, tval, mtype.String()) | ||||
| 			} | ||||
|  | ||||
| 			return val.Convert(mtype), nil | ||||
| 		case reflect.Interface: | ||||
| 			if mval1 == nil || mval1.IsNil() { | ||||
| 				return reflect.ValueOf(tval), nil | ||||
| 			} else { | ||||
| 				ival := mval1.Elem() | ||||
| 				return d.valueFromToml(mval1.Elem().Type(), t, &ival) | ||||
| 			} | ||||
| 		case reflect.Slice, reflect.Array: | ||||
| 			if isOtherSequence(mtype) && isOtherSequence(reflect.TypeOf(t)) { | ||||
| 				return d.valueFromOtherSliceI(mtype, t) | ||||
| 			} | ||||
| 			return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) | ||||
| 		default: | ||||
| 			return reflect.ValueOf(nil), fmt.Errorf("Can't convert %v(%T) to %v(%v)", tval, tval, mtype, mtype.Kind()) | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.Value, error) { | ||||
| 	val, err := d.valueFromToml(mtype.Elem(), tval) | ||||
| func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}, mval1 *reflect.Value) (reflect.Value, error) { | ||||
| 	var melem *reflect.Value | ||||
|  | ||||
| 	if mval1 != nil && !mval1.IsNil() && (mtype.Elem().Kind() == reflect.Struct || mtype.Elem().Kind() == reflect.Interface) { | ||||
| 		elem := mval1.Elem() | ||||
| 		melem = &elem | ||||
| 	} | ||||
|  | ||||
| 	val, err := d.valueFromToml(mtype.Elem(), tval, melem) | ||||
| 	if err != nil { | ||||
| 		return reflect.ValueOf(nil), err | ||||
| 	} | ||||
| @@ -744,6 +1100,12 @@ func (d *Decoder) unwrapPointer(mtype reflect.Type, tval interface{}) (reflect.V | ||||
| 	return mval, nil | ||||
| } | ||||
|  | ||||
| func (d *Decoder) unmarshalText(tval interface{}, mval reflect.Value) error { | ||||
| 	var buf bytes.Buffer | ||||
| 	fmt.Fprint(&buf, tval) | ||||
| 	return callTextUnmarshaler(mval, buf.Bytes()) | ||||
| } | ||||
|  | ||||
| func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { | ||||
| 	tag := vf.Tag.Get(an.tag) | ||||
| 	parse := strings.Split(tag, ",") | ||||
| @@ -756,6 +1118,7 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { | ||||
| 	defaultValue := vf.Tag.Get(tagDefault) | ||||
| 	result := tomlOpts{ | ||||
| 		name:         vf.Name, | ||||
| 		nameFromTag:  false, | ||||
| 		comment:      comment, | ||||
| 		commented:    commented, | ||||
| 		multiline:    multiline, | ||||
| @@ -768,6 +1131,7 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { | ||||
| 			result.include = false | ||||
| 		} else { | ||||
| 			result.name = strings.Trim(parse[0], " ") | ||||
| 			result.nameFromTag = true | ||||
| 		} | ||||
| 	} | ||||
| 	if vf.PkgPath != "" { | ||||
| @@ -784,11 +1148,7 @@ func tomlOptions(vf reflect.StructField, an annotation) tomlOpts { | ||||
|  | ||||
| func isZero(val reflect.Value) bool { | ||||
| 	switch val.Type().Kind() { | ||||
| 	case reflect.Map: | ||||
| 		fallthrough | ||||
| 	case reflect.Array: | ||||
| 		fallthrough | ||||
| 	case reflect.Slice: | ||||
| 	case reflect.Slice, reflect.Array, reflect.Map: | ||||
| 		return val.Len() == 0 | ||||
| 	default: | ||||
| 		return reflect.DeepEqual(val.Interface(), reflect.Zero(val.Type()).Interface()) | ||||
| @@ -801,3 +1161,80 @@ func formatError(err error, pos Position) error { | ||||
| 	} | ||||
| 	return fmt.Errorf("%s: %s", pos, err) | ||||
| } | ||||
|  | ||||
| // visitorState keeps track of which keys were unmarshaled. | ||||
| type visitorState struct { | ||||
| 	tree   *Tree | ||||
| 	path   []string | ||||
| 	keys   map[string]struct{} | ||||
| 	active bool | ||||
| } | ||||
|  | ||||
| func newVisitorState(tree *Tree) visitorState { | ||||
| 	path, result := []string{}, map[string]struct{}{} | ||||
| 	insertKeys(path, result, tree) | ||||
| 	return visitorState{ | ||||
| 		tree:   tree, | ||||
| 		path:   path[:0], | ||||
| 		keys:   result, | ||||
| 		active: true, | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *visitorState) push(key string) { | ||||
| 	if s.active { | ||||
| 		s.path = append(s.path, key) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *visitorState) pop() { | ||||
| 	if s.active { | ||||
| 		s.path = s.path[:len(s.path)-1] | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *visitorState) visit() { | ||||
| 	if s.active { | ||||
| 		delete(s.keys, strings.Join(s.path, ".")) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *visitorState) visitAll() { | ||||
| 	if s.active { | ||||
| 		for k := range s.keys { | ||||
| 			if strings.HasPrefix(k, strings.Join(s.path, ".")) { | ||||
| 				delete(s.keys, k) | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (s *visitorState) validate() error { | ||||
| 	if !s.active { | ||||
| 		return nil | ||||
| 	} | ||||
| 	undecoded := make([]string, 0, len(s.keys)) | ||||
| 	for key := range s.keys { | ||||
| 		undecoded = append(undecoded, key) | ||||
| 	} | ||||
| 	sort.Strings(undecoded) | ||||
| 	if len(undecoded) > 0 { | ||||
| 		return fmt.Errorf("undecoded keys: %q", undecoded) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func insertKeys(path []string, m map[string]struct{}, tree *Tree) { | ||||
| 	for k, v := range tree.values { | ||||
| 		switch node := v.(type) { | ||||
| 		case []*Tree: | ||||
| 			for i, item := range node { | ||||
| 				insertKeys(append(path, k, strconv.Itoa(i)), m, item) | ||||
| 			} | ||||
| 		case *Tree: | ||||
| 			insertKeys(append(path, k), m, node) | ||||
| 		case *tomlValue: | ||||
| 			m[strings.Join(append(path, k), ".")] = struct{}{} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|   | ||||
							
								
								
									
										17
									
								
								vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_Map_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										17
									
								
								vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_Map_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,17 +0,0 @@ | ||||
| title = "TOML Marshal Testing" | ||||
|  | ||||
| [basic_map] | ||||
|   one = "one" | ||||
|   two = "two" | ||||
|  | ||||
| [long_map] | ||||
|   a7 = "1" | ||||
|   b3 = "2" | ||||
|   c8 = "3" | ||||
|   d4 = "4" | ||||
|   e6 = "5" | ||||
|   f5 = "6" | ||||
|   g10 = "7" | ||||
|   h1 = "8" | ||||
|   i2 = "9" | ||||
|   j9 = "10" | ||||
							
								
								
									
										1
									
								
								vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/pelletier/go-toml/marshal_OrderPreserve_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -27,6 +27,7 @@ title = "TOML Marshal Testing" | ||||
|   uint = 5001 | ||||
|   bool = true | ||||
|   float = 123.4 | ||||
|   float64 = 123.456782132399 | ||||
|   int = 5000 | ||||
|   string = "Bite me" | ||||
|   date = 1979-05-27T07:32:00Z | ||||
|   | ||||
							
								
								
									
										1
									
								
								vendor/github.com/pelletier/go-toml/marshal_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								vendor/github.com/pelletier/go-toml/marshal_test.toml
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -4,6 +4,7 @@ title = "TOML Marshal Testing" | ||||
|   bool = true | ||||
|   date = 1979-05-27T07:32:00Z | ||||
|   float = 123.4 | ||||
|   float64 = 123.456782132399 | ||||
|   int = 5000 | ||||
|   string = "Bite me" | ||||
|   uint = 5001 | ||||
|   | ||||
							
								
								
									
										73
									
								
								vendor/github.com/pelletier/go-toml/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										73
									
								
								vendor/github.com/pelletier/go-toml/parser.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -158,6 +158,11 @@ func (p *tomlParser) parseGroup() tomlParserStateFn { | ||||
| 	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 | ||||
| @@ -201,6 +206,11 @@ func (p *tomlParser) parseAssign() tomlParserStateFn { | ||||
| 			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} | ||||
| @@ -313,7 +323,41 @@ func (p *tomlParser) parseRvalue() interface{} { | ||||
| 		} | ||||
| 		return val | ||||
| 	case tokenDate: | ||||
| 		val, err := time.ParseInLocation(time.RFC3339Nano, tok.val, time.UTC) | ||||
| 		layout := time.RFC3339Nano | ||||
| 		if !strings.Contains(tok.val, "T") { | ||||
| 			layout = strings.Replace(layout, "T", " ", 1) | ||||
| 		} | ||||
| 		val, err := time.ParseInLocation(layout, tok.val, time.UTC) | ||||
| 		if err != nil { | ||||
| 			p.raiseError(tok, "%s", err) | ||||
| 		} | ||||
| 		return val | ||||
| 	case tokenLocalDate: | ||||
| 		v := strings.Replace(tok.val, " ", "T", -1) | ||||
| 		isDateTime := false | ||||
| 		isTime := false | ||||
| 		for _, c := range v { | ||||
| 			if c == 'T' || c == 't' { | ||||
| 				isDateTime = true | ||||
| 				break | ||||
| 			} | ||||
| 			if c == ':' { | ||||
| 				isTime = true | ||||
| 				break | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		var val interface{} | ||||
| 		var err error | ||||
|  | ||||
| 		if isDateTime { | ||||
| 			val, err = ParseLocalDateTime(v) | ||||
| 		} else if isTime { | ||||
| 			val, err = ParseLocalTime(v) | ||||
| 		} else { | ||||
| 			val, err = ParseLocalDate(v) | ||||
| 		} | ||||
|  | ||||
| 		if err != nil { | ||||
| 			p.raiseError(tok, "%s", err) | ||||
| 		} | ||||
| @@ -356,12 +400,15 @@ Loop: | ||||
| 			} | ||||
| 			key := p.getToken() | ||||
| 			p.assume(tokenEqual) | ||||
| 			value := p.parseRvalue() | ||||
| 			tree.Set(key.val, value) | ||||
| 		case tokenComma: | ||||
| 			if previous == nil { | ||||
| 				p.raiseError(follow, "inline table cannot start with a comma") | ||||
|  | ||||
| 			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") | ||||
| 			} | ||||
| @@ -374,12 +421,13 @@ Loop: | ||||
| 	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(nil) | ||||
| 	arrayType := reflect.TypeOf(newTree()) | ||||
| 	for { | ||||
| 		follow := p.peek() | ||||
| 		if follow == nil || follow.typ == tokenEOF { | ||||
| @@ -390,11 +438,8 @@ func (p *tomlParser) parseArray() interface{} { | ||||
| 			break | ||||
| 		} | ||||
| 		val := p.parseRvalue() | ||||
| 		if arrayType == nil { | ||||
| 			arrayType = reflect.TypeOf(val) | ||||
| 		} | ||||
| 		if reflect.TypeOf(val) != arrayType { | ||||
| 			p.raiseError(follow, "mixed types in array") | ||||
| 			arrayType = nil | ||||
| 		} | ||||
| 		array = append(array, val) | ||||
| 		follow = p.peek() | ||||
| @@ -408,6 +453,12 @@ func (p *tomlParser) parseArray() interface{} { | ||||
| 			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, | ||||
|   | ||||
							
								
								
									
										22
									
								
								vendor/github.com/pelletier/go-toml/token.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										22
									
								
								vendor/github.com/pelletier/go-toml/token.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -1,10 +1,6 @@ | ||||
| package toml | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strconv" | ||||
| 	"unicode" | ||||
| ) | ||||
| import "fmt" | ||||
|  | ||||
| // Define tokens | ||||
| type tokenType int | ||||
| @@ -35,6 +31,7 @@ const ( | ||||
| 	tokenDoubleLeftBracket | ||||
| 	tokenDoubleRightBracket | ||||
| 	tokenDate | ||||
| 	tokenLocalDate | ||||
| 	tokenKeyGroup | ||||
| 	tokenKeyGroupArray | ||||
| 	tokenComma | ||||
| @@ -68,7 +65,8 @@ var tokenTypeNames = []string{ | ||||
| 	")", | ||||
| 	"]]", | ||||
| 	"[[", | ||||
| 	"Date", | ||||
| 	"LocalDate", | ||||
| 	"LocalDate", | ||||
| 	"KeyGroup", | ||||
| 	"KeyGroupArray", | ||||
| 	",", | ||||
| @@ -95,14 +93,6 @@ func (tt tokenType) String() string { | ||||
| 	return "Unknown" | ||||
| } | ||||
|  | ||||
| func (t token) Int() int { | ||||
| 	if result, err := strconv.Atoi(t.val); err != nil { | ||||
| 		panic(err) | ||||
| 	} else { | ||||
| 		return result | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func (t token) String() string { | ||||
| 	switch t.typ { | ||||
| 	case tokenEOF: | ||||
| @@ -119,7 +109,7 @@ func isSpace(r rune) bool { | ||||
| } | ||||
|  | ||||
| func isAlphanumeric(r rune) bool { | ||||
| 	return unicode.IsLetter(r) || r == '_' | ||||
| 	return 'a' <= r && r <= 'z' || 'A' <= r && r <= 'Z' || r == '_' | ||||
| } | ||||
|  | ||||
| func isKeyChar(r rune) bool { | ||||
| @@ -134,7 +124,7 @@ func isKeyStartChar(r rune) bool { | ||||
| } | ||||
|  | ||||
| func isDigit(r rune) bool { | ||||
| 	return unicode.IsNumber(r) | ||||
| 	return '0' <= r && r <= '9' | ||||
| } | ||||
|  | ||||
| func isHexDigit(r rune) bool { | ||||
|   | ||||
							
								
								
									
										6
									
								
								vendor/github.com/pelletier/go-toml/toml.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										6
									
								
								vendor/github.com/pelletier/go-toml/toml.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -23,6 +23,7 @@ type Tree struct { | ||||
| 	values    map[string]interface{} // string -> *tomlValue, *Tree, []*Tree | ||||
| 	comment   string | ||||
| 	commented bool | ||||
| 	inline    bool | ||||
| 	position  Position | ||||
| } | ||||
|  | ||||
| @@ -222,8 +223,12 @@ func (t *Tree) SetPathWithOptions(keys []string, opts SetOptions, value interfac | ||||
| 	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 | ||||
| @@ -307,6 +312,7 @@ func (t *Tree) createSubTree(keys []string, pos Position) error { | ||||
| 		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 | ||||
| 		} | ||||
|   | ||||
							
								
								
									
										151
									
								
								vendor/github.com/pelletier/go-toml/tomltree_write.go
									
									
									
										generated
									
									
										vendored
									
									
								
							
							
						
						
									
										151
									
								
								vendor/github.com/pelletier/go-toml/tomltree_write.go
									
									
									
										generated
									
									
										vendored
									
									
								
							| @@ -5,6 +5,7 @@ import ( | ||||
| 	"fmt" | ||||
| 	"io" | ||||
| 	"math" | ||||
| 	"math/big" | ||||
| 	"reflect" | ||||
| 	"sort" | ||||
| 	"strconv" | ||||
| @@ -27,23 +28,35 @@ type sortNode struct { | ||||
| // 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) string { | ||||
| func encodeMultilineTomlString(value string, commented string) string { | ||||
| 	var b bytes.Buffer | ||||
| 	adjacentQuoteCount := 0 | ||||
|  | ||||
| 	for _, rr := range value { | ||||
| 	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") | ||||
| 			b.WriteString("\n" + commented) | ||||
| 		case '\f': | ||||
| 			b.WriteString(`\f`) | ||||
| 		case '\r': | ||||
| 			b.WriteString("\r") | ||||
| 		case '"': | ||||
| 			b.WriteString(`"`) | ||||
| 			if adjacentQuoteCount >= 3 || i == len(value)-1 { | ||||
| 				adjacentQuoteCount = 0 | ||||
| 				b.WriteString(`\"`) | ||||
| 			} else { | ||||
| 				b.WriteString(`"`) | ||||
| 			} | ||||
| 		case '\\': | ||||
| 			b.WriteString(`\`) | ||||
| 		default: | ||||
| @@ -90,7 +103,30 @@ func encodeTomlString(value string) string { | ||||
| 	return b.String() | ||||
| } | ||||
|  | ||||
| func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElementPerLine bool) (string, error) { | ||||
| 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) | ||||
| @@ -106,20 +142,28 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen | ||||
| 	case int64: | ||||
| 		return strconv.FormatInt(value, 10), nil | ||||
| 	case float64: | ||||
| 		// Ensure a round float does contain a decimal point. Otherwise feeding | ||||
| 		// the output back to the parser would convert to an integer. | ||||
| 		if math.Trunc(value) == value { | ||||
| 			return strings.ToLower(strconv.FormatFloat(value, 'f', 1, 32)), nil | ||||
| 		// 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 | ||||
| 			} | ||||
| 		} | ||||
| 		return strings.ToLower(strconv.FormatFloat(value, 'f', -1, 32)), nil | ||||
| 		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 { | ||||
| 			return "\"\"\"\n" + encodeMultilineTomlString(value) + "\"\"\"", nil | ||||
| 			return "\"\"\"\n" + encodeMultilineTomlString(value, commented) + "\"\"\"", nil | ||||
| 		} | ||||
| 		return "\"" + encodeTomlString(value) + "\"", nil | ||||
| 	case []byte: | ||||
| 		b, _ := v.([]byte) | ||||
| 		return tomlValueStringRepresentation(string(b), indent, arraysOneElementPerLine) | ||||
| 		return tomlValueStringRepresentation(string(b), commented, indent, ord, arraysOneElementPerLine) | ||||
| 	case bool: | ||||
| 		if value { | ||||
| 			return "true", nil | ||||
| @@ -127,6 +171,14 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen | ||||
| 		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 | ||||
| 	} | ||||
| @@ -137,7 +189,7 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen | ||||
| 		var values []string | ||||
| 		for i := 0; i < rv.Len(); i++ { | ||||
| 			item := rv.Index(i).Interface() | ||||
| 			itemRepr, err := tomlValueStringRepresentation(item, indent, arraysOneElementPerLine) | ||||
| 			itemRepr, err := tomlValueStringRepresentation(item, commented, indent, ord, arraysOneElementPerLine) | ||||
| 			if err != nil { | ||||
| 				return "", err | ||||
| 			} | ||||
| @@ -151,16 +203,16 @@ func tomlValueStringRepresentation(v interface{}, indent string, arraysOneElemen | ||||
|  | ||||
| 			for _, value := range values { | ||||
| 				stringBuffer.WriteString(valueIndent) | ||||
| 				stringBuffer.WriteString(value) | ||||
| 				stringBuffer.WriteString(commented + value) | ||||
| 				stringBuffer.WriteString(`,`) | ||||
| 				stringBuffer.WriteString("\n") | ||||
| 			} | ||||
|  | ||||
| 			stringBuffer.WriteString(indent + "]") | ||||
| 			stringBuffer.WriteString(indent + commented + "]") | ||||
|  | ||||
| 			return stringBuffer.String(), nil | ||||
| 		} | ||||
| 		return "[" + strings.Join(values, ",") + "]", nil | ||||
| 		return "[" + strings.Join(values, ", ") + "]", nil | ||||
| 	} | ||||
| 	return "", fmt.Errorf("unsupported value type %T: %v", v, v) | ||||
| } | ||||
| @@ -255,10 +307,10 @@ func sortAlphabetical(t *Tree) (vals []sortNode) { | ||||
| } | ||||
|  | ||||
| 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) | ||||
| 	return t.writeToOrdered(w, indent, keyspace, bytesCount, arraysOneElementPerLine, OrderAlphabetical, "  ", false) | ||||
| } | ||||
|  | ||||
| func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder) (int64, error) { | ||||
| func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount int64, arraysOneElementPerLine bool, ord marshalOrder, indentString string, parentCommented bool) (int64, error) { | ||||
| 	var orderedVals []sortNode | ||||
|  | ||||
| 	switch ord { | ||||
| @@ -274,14 +326,10 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i | ||||
| 			k := node.key | ||||
| 			v := t.values[k] | ||||
|  | ||||
| 			combinedKey := k | ||||
| 			combinedKey := quoteKeyIfNeeded(k) | ||||
| 			if keyspace != "" { | ||||
| 				combinedKey = keyspace + "." + combinedKey | ||||
| 			} | ||||
| 			var commented string | ||||
| 			if t.commented { | ||||
| 				commented = "# " | ||||
| 			} | ||||
|  | ||||
| 			switch node := v.(type) { | ||||
| 			// node has to be of those two types given how keys are sorted above | ||||
| @@ -302,24 +350,33 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i | ||||
| 						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+"  ", combinedKey, bytesCount, arraysOneElementPerLine, ord) | ||||
| 				bytesCount, err = node.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, 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+"  ", combinedKey, bytesCount, arraysOneElementPerLine, ord) | ||||
| 					bytesCount, err = subTree.writeToOrdered(w, indent+indentString, combinedKey, bytesCount, arraysOneElementPerLine, ord, indentString, parentCommented || t.commented || subTree.commented) | ||||
| 					if err != nil { | ||||
| 						return bytesCount, err | ||||
| 					} | ||||
| @@ -332,7 +389,11 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i | ||||
| 				return bytesCount, fmt.Errorf("invalid value type at %s: %T", k, t.values[k]) | ||||
| 			} | ||||
|  | ||||
| 			repr, err := tomlValueStringRepresentation(v, indent, arraysOneElementPerLine) | ||||
| 			var commented string | ||||
| 			if parentCommented || t.commented || v.commented { | ||||
| 				commented = "# " | ||||
| 			} | ||||
| 			repr, err := tomlValueStringRepresentation(v, commented, indent, ord, arraysOneElementPerLine) | ||||
| 			if err != nil { | ||||
| 				return bytesCount, err | ||||
| 			} | ||||
| @@ -350,11 +411,8 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			var commented string | ||||
| 			if v.commented { | ||||
| 				commented = "# " | ||||
| 			} | ||||
| 			writtenBytesCount, err := writeStrings(w, indent, commented, k, " = ", repr, "\n") | ||||
| 			quotedKey := quoteKeyIfNeeded(k) | ||||
| 			writtenBytesCount, err := writeStrings(w, indent, commented, quotedKey, " = ", repr, "\n") | ||||
| 			bytesCount += int64(writtenBytesCount) | ||||
| 			if err != nil { | ||||
| 				return bytesCount, err | ||||
| @@ -365,6 +423,32 @@ func (t *Tree) writeToOrdered(w io.Writer, indent, keyspace string, bytesCount i | ||||
| 	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 { | ||||
| @@ -387,12 +471,11 @@ func (t *Tree) WriteTo(w io.Writer) (int64, error) { | ||||
| // 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) { | ||||
| 	var buf bytes.Buffer | ||||
| 	_, err := t.WriteTo(&buf) | ||||
| 	b, err := t.Marshal() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
| 	return buf.String(), nil | ||||
| 	return string(b), nil | ||||
| } | ||||
|  | ||||
| // String generates a human-readable representation of the current tree. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user