Compare commits
15 Commits
v2.0.0-beta.8
...
v2.0.2
| Author | SHA1 | Date | |
|---|---|---|---|
| 216628222f | |||
| 322e0b15d2 | |||
| 85bfc0ed51 | |||
| 295a720dfb | |||
| 0a422e3dbd | |||
| 627dade0c7 | |||
| b2e0231cc9 | |||
| ba95863cd3 | |||
| db679df765 | |||
| c5ca2c682b | |||
| ed80712cb4 | |||
| b24772942d | |||
| 9501a05ed7 | |||
| 171a592663 | |||
| 5aaf5ef13b |
@@ -35,11 +35,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v1
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
# If you wish to specify custom queries, you can do so here or in a config file.
|
||||
@@ -50,7 +50,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v1
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 https://git.io/JvXDl
|
||||
@@ -64,4 +64,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v1
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
||||
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: "ubuntu-latest"
|
||||
name: report
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup go
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Set up Go
|
||||
@@ -24,13 +24,13 @@ jobs:
|
||||
with:
|
||||
go-version: 1.18
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Run GoReleaser
|
||||
uses: goreleaser/goreleaser-action@v2
|
||||
uses: goreleaser/goreleaser-action@v3
|
||||
with:
|
||||
distribution: goreleaser
|
||||
version: latest
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
runs-on: ${{ matrix.os }}
|
||||
name: ${{ matrix.go }}/${{ matrix.os }}
|
||||
steps:
|
||||
- uses: actions/checkout@master
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup go ${{ matrix.go }}
|
||||
|
||||
@@ -16,7 +16,11 @@ builds:
|
||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
||||
targets:
|
||||
- linux_amd64
|
||||
- linux_arm64
|
||||
- linux_arm
|
||||
- windows_amd64
|
||||
- windows_arm64
|
||||
- windows_arm
|
||||
- darwin_amd64
|
||||
- darwin_arm64
|
||||
- id: tomljson
|
||||
@@ -31,7 +35,11 @@ builds:
|
||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
||||
targets:
|
||||
- linux_amd64
|
||||
- linux_arm64
|
||||
- linux_arm
|
||||
- windows_amd64
|
||||
- windows_arm64
|
||||
- windows_arm
|
||||
- darwin_amd64
|
||||
- darwin_arm64
|
||||
- id: jsontoml
|
||||
@@ -46,7 +54,11 @@ builds:
|
||||
mod_timestamp: '{{ .CommitTimestamp }}'
|
||||
targets:
|
||||
- linux_amd64
|
||||
- linux_arm64
|
||||
- linux_arm
|
||||
- windows_amd64
|
||||
- windows_arm64
|
||||
- windows_arm
|
||||
- darwin_amd64
|
||||
- darwin_arm64
|
||||
universal_binaries:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 - 2021 Thomas Pelletier, Eric Anderton
|
||||
Copyright (c) 2013 - 2022 Thomas Pelletier, Eric Anderton
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -4,17 +4,6 @@ Go library for the [TOML](https://toml.io/en/) format.
|
||||
|
||||
This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0).
|
||||
|
||||
## Development status
|
||||
|
||||
This is the upcoming major version of go-toml. It is currently in active
|
||||
development. As of release v2.0.0-beta.1, the library has reached feature parity
|
||||
with v1, and fixes a lot known bugs and performance issues along the way.
|
||||
|
||||
If you do not need the advanced document editing features of v1, you are
|
||||
encouraged to try out this version.
|
||||
|
||||
[👉 Roadmap for v2](https://github.com/pelletier/go-toml/discussions/506)
|
||||
|
||||
[🐞 Bug Reports](https://github.com/pelletier/go-toml/issues)
|
||||
|
||||
[💬 Anything else](https://github.com/pelletier/go-toml/discussions)
|
||||
@@ -49,7 +38,7 @@ operations should not be shockingly slow. See [benchmarks](#benchmarks).
|
||||
### Strict mode
|
||||
|
||||
`Decoder` can be set to "strict mode", which makes it error when some parts of
|
||||
the TOML document was not prevent in the target structure. This is a great way
|
||||
the TOML document was not present in the target structure. This is a great way
|
||||
to check for typos. [See example in the documentation][strict].
|
||||
|
||||
[strict]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Decoder.DisallowUnknownFields
|
||||
@@ -551,6 +540,13 @@ complete solutions exist out there.
|
||||
[query]: https://github.com/pelletier/go-toml/tree/f99d6bbca119636aeafcf351ee52b3d202782627/query
|
||||
[dasel]: https://github.com/TomWright/dasel
|
||||
|
||||
## Versioning
|
||||
|
||||
Go-toml follows [Semantic Versioning](http://semver.org/). The supported version
|
||||
of [TOML](https://github.com/toml-lang/toml) is indicated at the beginning of
|
||||
this document. The last two major versions of Go are supported
|
||||
(see [Go Release Policy](https://golang.org/doc/devel/release.html#policy)).
|
||||
|
||||
## License
|
||||
|
||||
The MIT License (MIT). Read [LICENSE](LICENSE).
|
||||
|
||||
@@ -2,4 +2,4 @@ module github.com/pelletier/go-toml/v2
|
||||
|
||||
go 1.16
|
||||
|
||||
require github.com/stretchr/testify v1.7.1
|
||||
require github.com/stretchr/testify v1.7.2
|
||||
|
||||
@@ -3,9 +3,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2 h1:4jaiDzPyXQvSd7D0EjG45355tLlV3VOECpq10pLC+8s=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
@@ -11,5 +11,6 @@ func TestEntrySize(t *testing.T) {
|
||||
// Validate no regression on the size of entry{}. This is a critical bit for
|
||||
// performance of unmarshaling documents. Should only be increased with care
|
||||
// and a very good reason.
|
||||
require.LessOrEqual(t, 48, int(unsafe.Sizeof(entry{})))
|
||||
maxExpectedEntrySize := 48
|
||||
require.LessOrEqual(t, int(unsafe.Sizeof(entry{})), maxExpectedEntrySize)
|
||||
}
|
||||
|
||||
+27
-4
@@ -107,6 +107,13 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
|
||||
// a newline character or a single quote. In that case they are emitted as
|
||||
// quoted strings.
|
||||
//
|
||||
// Unsigned integers larger than math.MaxInt64 cannot be encoded. Doing so
|
||||
// results in an error. This rule exists because the TOML specification only
|
||||
// requires parsers to support at least the 64 bits integer range. Allowing
|
||||
// larger numbers would create non-standard TOML documents, which may not be
|
||||
// readable (at best) by other implementations. To encode such numbers, a
|
||||
// solution is a custom type that implements encoding.TextMarshaler.
|
||||
//
|
||||
// When encoding structs, fields are encoded in order of definition, with their
|
||||
// exact name.
|
||||
//
|
||||
@@ -128,7 +135,8 @@ func (enc *Encoder) SetIndentTables(indent bool) *Encoder {
|
||||
//
|
||||
// In addition to the "toml" tag struct tag, a "comment" tag can be used to emit
|
||||
// a TOML comment before the value being annotated. Comments are ignored inside
|
||||
// inline tables.
|
||||
// inline tables. For array tables, the comment is only present before the first
|
||||
// element of the array.
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
var (
|
||||
b []byte
|
||||
@@ -302,7 +310,11 @@ func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, e
|
||||
b = append(b, "false"...)
|
||||
}
|
||||
case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint:
|
||||
b = strconv.AppendUint(b, v.Uint(), 10)
|
||||
x := v.Uint()
|
||||
if x > uint64(math.MaxInt64) {
|
||||
return nil, fmt.Errorf("toml: not encoding uint (%d) greater than max int64 (%d)", x, int64(math.MaxInt64))
|
||||
}
|
||||
b = strconv.AppendUint(b, x, 10)
|
||||
case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int:
|
||||
b = strconv.AppendInt(b, v.Int(), 10)
|
||||
default:
|
||||
@@ -652,10 +664,19 @@ func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]b
|
||||
}
|
||||
|
||||
func (enc *Encoder) encodeComment(indent int, comment string, b []byte) []byte {
|
||||
if comment != "" {
|
||||
for len(comment) > 0 {
|
||||
var line string
|
||||
idx := strings.IndexByte(comment, '\n')
|
||||
if idx >= 0 {
|
||||
line = comment[:idx]
|
||||
comment = comment[idx+1:]
|
||||
} else {
|
||||
line = comment
|
||||
comment = ""
|
||||
}
|
||||
b = enc.indent(indent, b)
|
||||
b = append(b, "# "...)
|
||||
b = append(b, comment...)
|
||||
b = append(b, line...)
|
||||
b = append(b, '\n')
|
||||
}
|
||||
return b
|
||||
@@ -881,6 +902,8 @@ func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.
|
||||
scratch = append(scratch, "]]\n"...)
|
||||
ctx.skipTableHeader = true
|
||||
|
||||
b = enc.encodeComment(ctx.indent, ctx.options.comment, b)
|
||||
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
b = append(b, scratch...)
|
||||
|
||||
|
||||
@@ -1004,6 +1004,22 @@ func TestIssue752(t *testing.T) {
|
||||
require.Equal(t, "", string(out))
|
||||
}
|
||||
|
||||
func TestIssue768(t *testing.T) {
|
||||
type cfg struct {
|
||||
Name string `comment:"This is a multiline comment.\nThis is line 2."`
|
||||
}
|
||||
|
||||
out, err := toml.Marshal(&cfg{})
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := `# This is a multiline comment.
|
||||
# This is line 2.
|
||||
Name = ''
|
||||
`
|
||||
|
||||
require.Equal(t, expected, string(out))
|
||||
}
|
||||
|
||||
func TestMarshalNestedAnonymousStructs(t *testing.T) {
|
||||
type Embedded struct {
|
||||
Value string `toml:"value" json:"value"`
|
||||
@@ -1086,6 +1102,19 @@ func TestLocalTime(t *testing.T) {
|
||||
require.Equal(t, expected, string(out))
|
||||
}
|
||||
|
||||
func TestMarshalUint64Overflow(t *testing.T) {
|
||||
// The TOML spec only requires implementation to provide support for the
|
||||
// int64 range. To avoid generating TOML documents that would not be
|
||||
// supported by standard-compliant parsers, uint64 > max int64 cannot be
|
||||
// marshaled.
|
||||
x := map[string]interface{}{
|
||||
"foo": uint64(math.MaxInt64) + 1,
|
||||
}
|
||||
|
||||
_, err := toml.Marshal(x)
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func ExampleMarshal() {
|
||||
type MyConfig struct {
|
||||
Version int
|
||||
|
||||
+27
-11
@@ -866,12 +866,27 @@ func (d *decoder) unmarshalFloat(value *ast.Node, v reflect.Value) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
|
||||
const (
|
||||
maxInt = int64(^uint(0) >> 1)
|
||||
minInt = -maxInt - 1
|
||||
)
|
||||
const (
|
||||
maxInt = int64(^uint(0) >> 1)
|
||||
minInt = -maxInt - 1
|
||||
)
|
||||
|
||||
// Maximum value of uint for decoding. Currently the decoder parses the integer
|
||||
// into an int64. As a result, on architectures where uint is 64 bits, the
|
||||
// effective maximum uint we can decode is the maximum of int64. On
|
||||
// architectures where uint is 32 bits, the maximum value we can decode is
|
||||
// lower: the maximum of uint32. I didn't find a way to figure out this value at
|
||||
// compile time, so it is computed during initialization.
|
||||
var maxUint int64 = math.MaxInt64
|
||||
|
||||
func init() {
|
||||
m := uint64(^uint(0))
|
||||
if m < uint64(maxUint) {
|
||||
maxUint = int64(m)
|
||||
}
|
||||
}
|
||||
|
||||
func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
|
||||
i, err := parseInteger(value.Data)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -932,7 +947,7 @@ func (d *decoder) unmarshalInteger(value *ast.Node, v reflect.Value) error {
|
||||
|
||||
r = reflect.ValueOf(uint8(i))
|
||||
case reflect.Uint:
|
||||
if i < 0 {
|
||||
if i < 0 || i > maxUint {
|
||||
return fmt.Errorf("toml: negative number %d does not fit in an uint", i)
|
||||
}
|
||||
|
||||
@@ -1167,11 +1182,6 @@ func forEachField(t reflect.Type, path []int, do func(name string, path []int))
|
||||
fieldPath := append(path, i)
|
||||
fieldPath = fieldPath[:len(fieldPath):len(fieldPath)]
|
||||
|
||||
if f.Anonymous {
|
||||
forEachField(f.Type, fieldPath, do)
|
||||
continue
|
||||
}
|
||||
|
||||
name := f.Tag.Get("toml")
|
||||
if name == "-" {
|
||||
continue
|
||||
@@ -1180,6 +1190,12 @@ func forEachField(t reflect.Type, path []int, do func(name string, path []int))
|
||||
if i := strings.IndexByte(name, ','); i >= 0 {
|
||||
name = name[:i]
|
||||
}
|
||||
|
||||
if f.Anonymous && name == "" {
|
||||
forEachField(f.Type, fieldPath, do)
|
||||
continue
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
name = f.Name
|
||||
}
|
||||
|
||||
+44
-1
@@ -554,7 +554,7 @@ wibble = 'wobble'
|
||||
[foo]
|
||||
|
||||
[foo.bar]
|
||||
huey = 'dewey'
|
||||
huey = 'dewey'
|
||||
`,
|
||||
gen: func() test {
|
||||
m := map[string]interface{}{}
|
||||
@@ -2380,6 +2380,49 @@ func TestIssue714(t *testing.T) {
|
||||
require.Error(t, err)
|
||||
}
|
||||
|
||||
func TestIssue772(t *testing.T) {
|
||||
type FileHandling struct {
|
||||
FilePattern string `toml:"pattern"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
FileHandling `toml:"filehandling"`
|
||||
}
|
||||
|
||||
var defaultConfigFile = []byte(`
|
||||
[filehandling]
|
||||
pattern = "reach-masterdev-"`)
|
||||
|
||||
config := Config{}
|
||||
err := toml.Unmarshal(defaultConfigFile, &config)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, "reach-masterdev-", config.FileHandling.FilePattern)
|
||||
}
|
||||
|
||||
func TestIssue774(t *testing.T) {
|
||||
type ScpData struct {
|
||||
Host string `json:"host"`
|
||||
}
|
||||
|
||||
type GenConfig struct {
|
||||
SCP []ScpData `toml:"scp" comment:"Array of Secure Copy Configurations"`
|
||||
}
|
||||
|
||||
c := &GenConfig{}
|
||||
c.SCP = []ScpData{{Host: "main.domain.com"}}
|
||||
|
||||
b, err := toml.Marshal(c)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected := `# Array of Secure Copy Configurations
|
||||
[[scp]]
|
||||
Host = 'main.domain.com'
|
||||
|
||||
`
|
||||
|
||||
require.Equal(t, expected, string(b))
|
||||
}
|
||||
|
||||
func TestUnmarshalDecodeErrors(t *testing.T) {
|
||||
examples := []struct {
|
||||
desc string
|
||||
|
||||
Reference in New Issue
Block a user