1102 changed files with 93 additions and 483360 deletions
@ -1,63 +0,0 @@
@@ -1,63 +0,0 @@
|
||||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. |
||||
|
||||
|
||||
[[projects]] |
||||
name = "github.com/BurntSushi/toml" |
||||
packages = ["."] |
||||
revision = "b26d9c308763d68093482582cea63d69be07a0f0" |
||||
version = "v0.3.0" |
||||
|
||||
[[projects]] |
||||
name = "github.com/gorilla/securecookie" |
||||
packages = ["."] |
||||
revision = "667fe4e3466a040b780561fe9b51a83a3753eefc" |
||||
version = "v1.1" |
||||
|
||||
[[projects]] |
||||
name = "github.com/jessevdk/go-flags" |
||||
packages = ["."] |
||||
revision = "96dc06278ce32a0e9d957d590bb987c81ee66407" |
||||
version = "v1.3.0" |
||||
|
||||
[[projects]] |
||||
branch = "master" |
||||
name = "github.com/jmoiron/sqlx" |
||||
packages = [".","reflectx"] |
||||
revision = "de8647470aafe4854c976707c431dbe1eb2822c6" |
||||
|
||||
[[projects]] |
||||
name = "github.com/mattn/go-sqlite3" |
||||
packages = ["."] |
||||
revision = "ed69081a91fd053f17672236b0dd52ba7485e1a3" |
||||
version = "v1.4.0" |
||||
|
||||
[[projects]] |
||||
name = "github.com/pkg/errors" |
||||
packages = ["."] |
||||
revision = "645ef00459ed84a119197bfb8d8205042c6df63d" |
||||
version = "v0.8.0" |
||||
|
||||
[[projects]] |
||||
branch = "master" |
||||
name = "golang.org/x/crypto" |
||||
packages = ["sha3"] |
||||
revision = "d585fd2cc9195196078f516b69daff6744ef5e84" |
||||
|
||||
[[projects]] |
||||
branch = "master" |
||||
name = "golang.org/x/net" |
||||
packages = ["context"] |
||||
revision = "d866cfc389cec985d6fda2859936a575a55a3ab6" |
||||
|
||||
[[projects]] |
||||
branch = "v2" |
||||
name = "gopkg.in/sorcix/irc.v2" |
||||
packages = [".","internal"] |
||||
revision = "1b25be7f891d1bd0190ac0ef159da153c9ffa22a" |
||||
|
||||
[solve-meta] |
||||
analyzer-name = "dep" |
||||
analyzer-version = 1 |
||||
inputs-digest = "2597d02f0d1ff0af313642458ae19f0dabc6e5464adc94013e82fa3285a75c4e" |
||||
solver-name = "gps-cdcl" |
||||
solver-version = 1 |
@ -1,34 +0,0 @@
@@ -1,34 +0,0 @@
|
||||
|
||||
# Gopkg.toml example |
||||
# |
||||
# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md |
||||
# for detailed Gopkg.toml documentation. |
||||
# |
||||
# required = ["github.com/user/thing/cmd/thing"] |
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] |
||||
# |
||||
# [[constraint]] |
||||
# name = "github.com/user/project" |
||||
# version = "1.0.0" |
||||
# |
||||
# [[constraint]] |
||||
# name = "github.com/user/project2" |
||||
# branch = "dev" |
||||
# source = "github.com/myfork/project2" |
||||
# |
||||
# [[override]] |
||||
# name = "github.com/x/y" |
||||
# version = "2.4.0" |
||||
|
||||
|
||||
[[constraint]] |
||||
name = "github.com/BurntSushi/toml" |
||||
version = "0.3.0" |
||||
|
||||
[[constraint]] |
||||
branch = "master" |
||||
name = "github.com/orcaman/concurrent-map" |
||||
|
||||
[[constraint]] |
||||
branch = "v2" |
||||
name = "gopkg.in/sorcix/irc.v2" |
@ -0,0 +1,17 @@
@@ -0,0 +1,17 @@
|
||||
module github.com/sageru-6ch/anonircd |
||||
|
||||
go 1.12 |
||||
|
||||
require ( |
||||
github.com/BurntSushi/toml v0.3.1 |
||||
github.com/go-sql-driver/mysql v1.4.1 // indirect |
||||
github.com/gorilla/securecookie v1.1.1 |
||||
github.com/jessevdk/go-flags v1.4.0 |
||||
github.com/jmoiron/sqlx v1.2.0 |
||||
github.com/mattn/go-sqlite3 v1.10.0 |
||||
github.com/pkg/errors v0.8.1 |
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c |
||||
golang.org/x/net v0.0.0-20190327214358-63eda1eb0650 // indirect |
||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc // indirect |
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20190306112350-8d7a73540b90 |
||||
) |
@ -0,0 +1,35 @@
@@ -0,0 +1,35 @@
|
||||
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= |
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= |
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= |
||||
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= |
||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= |
||||
github.com/gorilla/securecookie v0.0.0-20160422134519-667fe4e3466a/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= |
||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ= |
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4= |
||||
github.com/jessevdk/go-flags v1.3.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= |
||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA= |
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= |
||||
github.com/jmoiron/sqlx v0.0.0-20171211234905-de8647470aaf/go.mod h1:IiEW3SEiiErVyFdH8NTuWjSifiEQKUoyK3LNqr2kCHU= |
||||
github.com/jmoiron/sqlx v1.2.0 h1:41Ip0zITnmWNR/vHV+S4m+VoUivnWY5E4OJfLZjCJMA= |
||||
github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhBSsks= |
||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= |
||||
github.com/mattn/go-sqlite3 v1.4.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= |
||||
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= |
||||
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o= |
||||
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= |
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= |
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= |
||||
golang.org/x/crypto v0.0.0-20171219041129-d585fd2cc919/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= |
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= |
||||
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= |
||||
golang.org/x/net v0.0.0-20171212005608-d866cfc389ce/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= |
||||
golang.org/x/net v0.0.0-20190327214358-63eda1eb0650/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= |
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc h1:4gbWbmmPFp4ySWICouJl6emP0MyS31yy9SrTlAGFT+g= |
||||
golang.org/x/sys v0.0.0-20190322080309-f49334f85ddc/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= |
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= |
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20170726154628-1b25be7f891d/go.mod h1:9LLe1SvUK2YoWyIuJ+AParKHhu749G8oM+HTQQMZz9E= |
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20190306112350-8d7a73540b90 h1:ItuFAq9SlPhZvdIvsdgoE38i9aLLdDpBbFV9vTJhlp8= |
||||
gopkg.in/sorcix/irc.v2 v2.0.0-20190306112350-8d7a73540b90/go.mod h1:PmJkUcwbuPi1FiZ9Rarr6wzVMvzkO7uWqH1jwrMkgW0= |
@ -0,0 +1,33 @@
@@ -0,0 +1,33 @@
|
||||
project_name: stick |
||||
builds: |
||||
- |
||||
env: |
||||
- CGO_ENABLED=0 |
||||
ldflags: |
||||
- -s -w -X main.version={{.Version}} |
||||
goos: |
||||
- darwin |
||||
- freebsd |
||||
- linux |
||||
- windows |
||||
goarch: |
||||
- 386 |
||||
- amd64 |
||||
- arm |
||||
- arm64 |
||||
- ppc64 |
||||
- ppc64le |
||||
goarm: |
||||
- 6 |
||||
- 7 |
||||
archive: |
||||
replacements: |
||||
386: i386 |
||||
format_overrides: |
||||
- goos: windows |
||||
format: zip |
||||
files: |
||||
- LICENSE |
||||
- README.md |
||||
checksum: |
||||
name_template: 'checksums.txt' |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
TAGS |
||||
tags |
||||
.*.swp |
||||
tomlcheck/tomlcheck |
||||
toml.test |
@ -1,15 +0,0 @@
@@ -1,15 +0,0 @@
|
||||
language: go |
||||
go: |
||||
- 1.1 |
||||
- 1.2 |
||||
- 1.3 |
||||
- 1.4 |
||||
- 1.5 |
||||
- 1.6 |
||||
- tip |
||||
install: |
||||
- go install ./... |
||||
- go get github.com/BurntSushi/toml-test |
||||
script: |
||||
- export PATH="$PATH:$HOME/gopath/bin" |
||||
- make test |
@ -1,3 +0,0 @@
@@ -1,3 +0,0 @@
|
||||
Compatible with TOML version |
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/v0.4.0/versions/en/toml-v0.4.0.md) |
||||
|
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
Version 2, December 2004 |
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> |
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified |
||||
copies of this license document, and changing it is allowed as long |
||||
as the name is changed. |
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO. |
||||
|
@ -1,19 +0,0 @@
@@ -1,19 +0,0 @@
|
||||
install: |
||||
go install ./...
|
||||
|
||||
test: install |
||||
go test -v
|
||||
toml-test toml-test-decoder
|
||||
toml-test -encoder toml-test-encoder
|
||||
|
||||
fmt: |
||||
gofmt -w *.go */*.go
|
||||
colcheck *.go */*.go
|
||||
|
||||
tags: |
||||
find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
|
||||
|
||||
push: |
||||
git push origin master
|
||||
git push github master
|
||||
|
@ -1,218 +0,0 @@
@@ -1,218 +0,0 @@
|
||||
## TOML parser and encoder for Go with reflection |
||||
|
||||
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a |
||||
reflection interface similar to Go's standard library `json` and `xml` |
||||
packages. This package also supports the `encoding.TextUnmarshaler` and |
||||
`encoding.TextMarshaler` interfaces so that you can define custom data |
||||
representations. (There is an example of this below.) |
||||
|
||||
Spec: https://github.com/toml-lang/toml |
||||
|
||||
Compatible with TOML version |
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) |
||||
|
||||
Documentation: https://godoc.org/github.com/BurntSushi/toml |
||||
|
||||
Installation: |
||||
|
||||
```bash |
||||
go get github.com/BurntSushi/toml |
||||
``` |
||||
|
||||
Try the toml validator: |
||||
|
||||
```bash |
||||
go get github.com/BurntSushi/toml/cmd/tomlv |
||||
tomlv some-toml-file.toml |
||||
``` |
||||
|
||||
[](https://travis-ci.org/BurntSushi/toml) [](https://godoc.org/github.com/BurntSushi/toml) |
||||
|
||||
### Testing |
||||
|
||||
This package passes all tests in |
||||
[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder |
||||
and the encoder. |
||||
|
||||
### Examples |
||||
|
||||
This package works similarly to how the Go standard library handles `XML` |
||||
and `JSON`. Namely, data is loaded into Go values via reflection. |
||||
|
||||
For the simplest example, consider some TOML file as just a list of keys |
||||
and values: |
||||
|
||||
```toml |
||||
Age = 25 |
||||
Cats = [ "Cauchy", "Plato" ] |
||||
Pi = 3.14 |
||||
Perfection = [ 6, 28, 496, 8128 ] |
||||
DOB = 1987-07-05T05:45:00Z |
||||
``` |
||||
|
||||
Which could be defined in Go as: |
||||
|
||||
```go |
||||
type Config struct { |
||||
Age int |
||||
Cats []string |
||||
Pi float64 |
||||
Perfection []int |
||||
DOB time.Time // requires `import time` |
||||
} |
||||
``` |
||||
|
||||
And then decoded with: |
||||
|
||||
```go |
||||
var conf Config |
||||
if _, err := toml.Decode(tomlData, &conf); err != nil { |
||||
// handle error |
||||
} |
||||
``` |
||||
|
||||
You can also use struct tags if your struct field name doesn't map to a TOML |
||||
key value directly: |
||||
|
||||
```toml |
||||
some_key_NAME = "wat" |
||||
``` |
||||
|
||||
```go |
||||
type TOML struct { |
||||
ObscureKey string `toml:"some_key_NAME"` |
||||
} |
||||
``` |
||||
|
||||
### Using the `encoding.TextUnmarshaler` interface |
||||
|
||||
Here's an example that automatically parses duration strings into |
||||
`time.Duration` values: |
||||
|
||||
```toml |
||||
[[song]] |
||||
name = "Thunder Road" |
||||
duration = "4m49s" |
||||
|
||||
[[song]] |
||||
name = "Stairway to Heaven" |
||||
duration = "8m03s" |
||||
``` |
||||
|
||||
Which can be decoded with: |
||||
|
||||
```go |
||||
type song struct { |
||||
Name string |
||||
Duration duration |
||||
} |
||||
type songs struct { |
||||
Song []song |
||||
} |
||||
var favorites songs |
||||
if _, err := toml.Decode(blob, &favorites); err != nil { |
||||
log.Fatal(err) |
||||
} |
||||
|
||||
for _, s := range favorites.Song { |
||||
fmt.Printf("%s (%s)\n", s.Name, s.Duration) |
||||
} |
||||
``` |
||||
|
||||
And you'll also need a `duration` type that satisfies the |
||||
`encoding.TextUnmarshaler` interface: |
||||
|
||||
```go |
||||
type duration struct { |
||||
time.Duration |
||||
} |
||||
|
||||
func (d *duration) UnmarshalText(text []byte) error { |
||||
var err error |
||||
d.Duration, err = time.ParseDuration(string(text)) |
||||
return err |
||||
} |
||||
``` |
||||
|
||||
### More complex usage |
||||
|
||||
Here's an example of how to load the example from the official spec page: |
||||
|
||||
```toml |
||||
# This is a TOML document. Boom. |
||||
|
||||
title = "TOML Example" |
||||
|
||||
[owner] |
||||
name = "Tom Preston-Werner" |
||||
organization = "GitHub" |
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." |
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not? |
||||
|
||||
[database] |
||||
server = "192.168.1.1" |
||||
ports = [ 8001, 8001, 8002 ] |
||||
connection_max = 5000 |
||||
enabled = true |
||||
|
||||
[servers] |
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care. |
||||
[servers.alpha] |
||||
ip = "10.0.0.1" |
||||
dc = "eqdc10" |
||||
|
||||
[servers.beta] |
||||
ip = "10.0.0.2" |
||||
dc = "eqdc10" |
||||
|
||||
[clients] |
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it |
||||
|
||||
# Line breaks are OK when inside arrays |
||||
hosts = [ |
||||
"alpha", |
||||
"omega" |
||||
] |
||||
``` |
||||
|
||||
And the corresponding Go types are: |
||||
|
||||
```go |
||||
type tomlConfig struct { |
||||
Title string |
||||
Owner ownerInfo |
||||
DB database `toml:"database"` |
||||
Servers map[string]server |
||||
Clients clients |
||||
} |
||||
|
||||
type ownerInfo struct { |
||||
Name string |
||||
Org string `toml:"organization"` |
||||
Bio string |
||||
DOB time.Time |
||||
} |
||||
|
||||
type database struct { |
||||
Server string |
||||
Ports []int |
||||
ConnMax int `toml:"connection_max"` |
||||
Enabled bool |
||||
} |
||||
|
||||
type server struct { |
||||
IP string |
||||
DC string |
||||
} |
||||
|
||||
type clients struct { |
||||
Data [][]interface{} |
||||
Hosts []string |
||||
} |
||||
``` |
||||
|
||||
Note that a case insensitive match will be tried if an exact match can't be |
||||
found. |
||||
|
||||
A working example of the above can be found in `_examples/example.{go,toml}`. |
@ -1,61 +0,0 @@
@@ -1,61 +0,0 @@
|
||||
package main |
||||
|
||||
import ( |
||||
"fmt" |
||||
"time" |
||||
|
||||
"github.com/BurntSushi/toml" |
||||
) |
||||
|
||||
type tomlConfig struct { |
||||
Title string |
||||
Owner ownerInfo |
||||
DB database `toml:"database"` |
||||
Servers map[string]server |
||||
Clients clients |
||||
} |
||||
|
||||
type ownerInfo struct { |
||||
Name string |
||||
Org string `toml:"organization"` |
||||
Bio string |
||||
DOB time.Time |
||||
} |
||||
|
||||
type database struct { |
||||
Server string |
||||
Ports []int |
||||
ConnMax int `toml:"connection_max"` |
||||
Enabled bool |
||||
} |
||||
|
||||
type server struct { |
||||
IP string |
||||
DC string |
||||
} |
||||
|
||||
type clients struct { |
||||
Data [][]interface{} |
||||
Hosts []string |
||||
} |
||||
|
||||
func main() { |
||||
var config tomlConfig |
||||
if _, err := toml.DecodeFile("example.toml", &config); err != nil { |
||||
fmt.Println(err) |
||||
return |
||||
} |
||||
|
||||
fmt.Printf("Title: %s\n", config.Title) |
||||
fmt.Printf("Owner: %s (%s, %s), Born: %s\n", |
||||
config.Owner.Name, config.Owner.Org, config.Owner.Bio, |
||||
config.Owner.DOB) |
||||
fmt.Printf("Database: %s %v (Max conn. %d), Enabled? %v\n", |
||||
config.DB.Server, config.DB.Ports, config.DB.ConnMax, |
||||
config.DB.Enabled) |
||||
for serverName, server := range config.Servers { |
||||
fmt.Printf("Server: %s (%s, %s)\n", serverName, server.IP, server.DC) |
||||
} |
||||
fmt.Printf("Client data: %v\n", config.Clients.Data) |
||||
fmt.Printf("Client hosts: %v\n", config.Clients.Hosts) |
||||
} |
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
# This is a TOML document. Boom. |
||||
|
||||
title = "TOML Example" |
||||
|
||||
[owner] |
||||
name = "Tom Preston-Werner" |
||||
organization = "GitHub" |
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." |
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not? |
||||
|
||||
[database] |
||||
server = "192.168.1.1" |
||||
ports = [ 8001, 8001, 8002 ] |
||||
connection_max = 5000 |
||||
enabled = true |
||||
|
||||
[servers] |
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care. |
||||
[servers.alpha] |
||||
ip = "10.0.0.1" |
||||
dc = "eqdc10" |
||||
|
||||
[servers.beta] |
||||
ip = "10.0.0.2" |
||||
dc = "eqdc10" |
||||
|
||||
[clients] |
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it |
||||
|
||||
# Line breaks are OK when inside arrays |
||||
hosts = [ |
||||
"alpha", |
||||
"omega" |
||||
] |
@ -1,22 +0,0 @@
@@ -1,22 +0,0 @@
|
||||
# Test file for TOML |
||||
# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate |
||||
# This part you'll really hate |
||||
|
||||
[the] |
||||
test_string = "You'll hate me after this - #" # " Annoying, isn't it? |
||||
|
||||
[the.hard] |
||||
test_array = [ "] ", " # "] # ] There you go, parse this! |
||||
test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ] |
||||
# You didn't think it'd as easy as chucking out the last #, did you? |
||||
another_test_string = " Same thing, but with a string #" |
||||
harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too" |
||||
# Things will get harder |
||||
|
||||
[the.hard.bit#] |
||||
what? = "You don't think some user won't do that?" |
||||
multi_line_array = [ |
||||
"]", |
||||
# ] Oh yes I did |
||||
] |
||||
|
@ -1,4 +0,0 @@
@@ -1,4 +0,0 @@
|
||||
# [x] you |
||||
# [x.y] don't |
||||
# [x.y.z] need these |
||||
[x.y.z.w] # for this to work |
@ -1,6 +0,0 @@
@@ -1,6 +0,0 @@
|
||||
# DO NOT WANT |
||||
[fruit] |
||||
type = "apple" |
||||
|
||||
[fruit.type] |
||||
apple = "yes" |
@ -1,35 +0,0 @@
@@ -1,35 +0,0 @@
|
||||
# This is an INVALID TOML document. Boom. |
||||
# Can you spot the error without help? |
||||
|
||||
title = "TOML Example" |
||||
|
||||
[owner] |
||||
name = "Tom Preston-Werner" |
||||
organization = "GitHub" |
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer." |
||||
dob = 1979-05-27T7:32:00Z # First class dates? Why not? |
||||
|
||||
[database] |
||||
server = "192.168.1.1" |
||||
ports = [ 8001, 8001, 8002 ] |
||||
connection_max = 5000 |
||||
enabled = true |
||||
|
||||
[servers] |
||||
# You can indent as you please. Tabs or spaces. TOML don't care. |
||||
[servers.alpha] |
||||
ip = "10.0.0.1" |
||||
dc = "eqdc10" |
||||
|
||||
[servers.beta] |
||||
ip = "10.0.0.2" |
||||
dc = "eqdc10" |
||||
|
||||
[clients] |
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it |
||||
|
||||
# Line breaks are OK when inside arrays |
||||
hosts = [ |
||||
"alpha", |
||||
"omega" |
||||
] |
@ -1,5 +0,0 @@
@@ -1,5 +0,0 @@
|
||||
Age = 25 |
||||
Cats = [ "Cauchy", "Plato" ] |
||||
Pi = 3.14 |
||||
Perfection = [ 6, 28, 496, 8128 ] |
||||
DOB = 1987-07-05T05:45:00Z |
@ -1 +0,0 @@
@@ -1 +0,0 @@
|
||||
some_key_NAME = "wat" |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
Version 2, December 2004 |
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> |
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified |
||||
copies of this license document, and changing it is allowed as long |
||||
as the name is changed. |
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO. |
||||
|
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
# Implements the TOML test suite interface |
||||
|
||||
This is an implementation of the interface expected by |
||||
[toml-test](https://github.com/BurntSushi/toml-test) for my |
||||
[toml parser written in Go](https://github.com/BurntSushi/toml). |
||||
In particular, it maps TOML data on `stdin` to a JSON format on `stdout`. |
||||
|
||||
|
||||
Compatible with TOML version |
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) |
||||
|
||||
Compatible with `toml-test` version |
||||
[v0.2.0](https://github.com/BurntSushi/toml-test/tree/v0.2.0) |
@ -1,90 +0,0 @@
@@ -1,90 +0,0 @@
|
||||
// Command toml-test-decoder satisfies the toml-test interface for testing
|
||||
// TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout.
|
||||
package main |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"flag" |
||||
"fmt" |
||||
"log" |
||||
"os" |
||||
"path" |
||||
"time" |
||||
|
||||
"github.com/BurntSushi/toml" |
||||
) |
||||
|
||||
func init() { |
||||
log.SetFlags(0) |
||||
|
||||
flag.Usage = usage |
||||
flag.Parse() |
||||
} |
||||
|
||||
func usage() { |
||||
log.Printf("Usage: %s < toml-file\n", path.Base(os.Args[0])) |
||||
flag.PrintDefaults() |
||||
|
||||
os.Exit(1) |
||||
} |
||||
|
||||
func main() { |
||||
if flag.NArg() != 0 { |
||||
flag.Usage() |
||||
} |
||||
|
||||
var tmp interface{} |
||||
if _, err := toml.DecodeReader(os.Stdin, &tmp); err != nil { |
||||
log.Fatalf("Error decoding TOML: %s", err) |
||||
} |
||||
|
||||
typedTmp := translate(tmp) |
||||
if err := json.NewEncoder(os.Stdout).Encode(typedTmp); err != nil { |
||||
log.Fatalf("Error encoding JSON: %s", err) |
||||
} |
||||
} |
||||
|
||||
func translate(tomlData interface{}) interface{} { |
||||
switch orig := tomlData.(type) { |
||||
case map[string]interface{}: |
||||
typed := make(map[string]interface{}, len(orig)) |
||||
for k, v := range orig { |
||||
typed[k] = translate(v) |
||||
} |
||||
return typed |
||||
case []map[string]interface{}: |
||||
typed := make([]map[string]interface{}, len(orig)) |
||||
for i, v := range orig { |
||||
typed[i] = translate(v).(map[string]interface{}) |
||||
} |
||||
return typed |
||||
case []interface{}: |
||||
typed := make([]interface{}, len(orig)) |
||||
for i, v := range orig { |
||||
typed[i] = translate(v) |
||||
} |
||||
|
||||
// We don't really need to tag arrays, but let's be future proof.
|
||||
// (If TOML ever supports tuples, we'll need this.)
|
||||
return tag("array", typed) |
||||
case time.Time: |
||||
return tag("datetime", orig.Format("2006-01-02T15:04:05Z")) |
||||
case bool: |
||||
return tag("bool", fmt.Sprintf("%v", orig)) |
||||
case int64: |
||||
return tag("integer", fmt.Sprintf("%d", orig)) |
||||
case float64: |
||||
return tag("float", fmt.Sprintf("%v", orig)) |
||||
case string: |
||||
return tag("string", orig) |
||||
} |
||||
|
||||
panic(fmt.Sprintf("Unknown type: %T", tomlData)) |
||||
} |
||||
|
||||
func tag(typeName string, data interface{}) map[string]interface{} { |
||||
return map[string]interface{}{ |
||||
"type": typeName, |
||||
"value": data, |
||||
} |
||||
} |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
Version 2, December 2004 |
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> |
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified |
||||
copies of this license document, and changing it is allowed as long |
||||
as the name is changed. |
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO. |
||||
|
@ -1,13 +0,0 @@
@@ -1,13 +0,0 @@
|
||||
# Implements the TOML test suite interface for TOML encoders |
||||
|
||||
This is an implementation of the interface expected by |
||||
[toml-test](https://github.com/BurntSushi/toml-test) for the |
||||
[TOML encoder](https://github.com/BurntSushi/toml). |
||||
In particular, it maps JSON data on `stdin` to a TOML format on `stdout`. |
||||
|
||||
|
||||
Compatible with TOML version |
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) |
||||
|
||||
Compatible with `toml-test` version |
||||
[v0.2.0](https://github.com/BurntSushi/toml-test/tree/v0.2.0) |
@ -1,131 +0,0 @@
@@ -1,131 +0,0 @@
|
||||
// Command toml-test-encoder satisfies the toml-test interface for testing
|
||||
// TOML encoders. Namely, it accepts JSON on stdin and outputs TOML on stdout.
|
||||
package main |
||||
|
||||
import ( |
||||
"encoding/json" |
||||
"flag" |
||||
"log" |
||||
"os" |
||||
"path" |
||||
"strconv" |
||||
"time" |
||||
|
||||
"github.com/BurntSushi/toml" |
||||
) |
||||
|
||||
func init() { |
||||
log.SetFlags(0) |
||||
|
||||
flag.Usage = usage |
||||
flag.Parse() |
||||
} |
||||
|
||||
func usage() { |
||||
log.Printf("Usage: %s < json-file\n", path.Base(os.Args[0])) |
||||
flag.PrintDefaults() |
||||
|
||||
os.Exit(1) |
||||
} |
||||
|
||||
func main() { |
||||
if flag.NArg() != 0 { |
||||
flag.Usage() |
||||
} |
||||
|
||||
var tmp interface{} |
||||
if err := json.NewDecoder(os.Stdin).Decode(&tmp); err != nil { |
||||
log.Fatalf("Error decoding JSON: %s", err) |
||||
} |
||||
|
||||
tomlData := translate(tmp) |
||||
if err := toml.NewEncoder(os.Stdout).Encode(tomlData); err != nil { |
||||
log.Fatalf("Error encoding TOML: %s", err) |
||||
} |
||||
} |
||||
|
||||
func translate(typedJson interface{}) interface{} { |
||||
switch v := typedJson.(type) { |
||||
case map[string]interface{}: |
||||
if len(v) == 2 && in("type", v) && in("value", v) { |
||||
return untag(v) |
||||
} |
||||
m := make(map[string]interface{}, len(v)) |
||||
for k, v2 := range v { |
||||
m[k] = translate(v2) |
||||
} |
||||
return m |
||||
case []interface{}: |
||||
tabArray := make([]map[string]interface{}, len(v)) |
||||
for i := range v { |
||||
if m, ok := translate(v[i]).(map[string]interface{}); ok { |
||||
tabArray[i] = m |
||||
} else { |
||||
log.Fatalf("JSON arrays may only contain objects. This " + |
||||
"corresponds to only tables being allowed in " + |
||||
"TOML table arrays.") |
||||
} |
||||
} |
||||
return tabArray |
||||
} |
||||
log.Fatalf("Unrecognized JSON format '%T'.", typedJson) |
||||
panic("unreachable") |
||||
} |
||||
|
||||
func untag(typed map[string]interface{}) interface{} { |
||||
t := typed["type"].(string) |
||||
v := typed["value"] |
||||
switch t { |
||||
case "string": |
||||
return v.(string) |
||||
case "integer": |
||||
v := v.(string) |
||||
n, err := strconv.Atoi(v) |
||||
if err != nil { |
||||
log.Fatalf("Could not parse '%s' as integer: %s", v, err) |
||||
} |
||||
return n |
||||
case "float": |
||||
v := v.(string) |
||||
f, err := strconv.ParseFloat(v, 64) |
||||
if err != nil { |
||||
log.Fatalf("Could not parse '%s' as float64: %s", v, err) |
||||
} |
||||
return f |
||||
case "datetime": |
||||
v := v.(string) |
||||
t, err := time.Parse("2006-01-02T15:04:05Z", v) |
||||
if err != nil { |
||||
log.Fatalf("Could not parse '%s' as a datetime: %s", v, err) |
||||
} |
||||
return t |
||||
case "bool": |
||||
v := v.(string) |
||||
switch v { |
||||
case "true": |
||||
return true |
||||
case "false": |
||||
return false |
||||
} |
||||
log.Fatalf("Could not parse '%s' as a boolean.", v) |
||||
case "array": |
||||
v := v.([]interface{}) |
||||
array := make([]interface{}, len(v)) |
||||
for i := range v { |
||||
if m, ok := v[i].(map[string]interface{}); ok { |
||||
array[i] = untag(m) |
||||
} else { |
||||
log.Fatalf("Arrays may only contain other arrays or "+ |
||||
"primitive values, but found a '%T'.", m) |
||||
} |
||||
} |
||||
return array |
||||
} |
||||
log.Fatalf("Unrecognized tag type '%s'.", t) |
||||
panic("unreachable") |
||||
} |
||||
|
||||
func in(key string, m map[string]interface{}) bool { |
||||
_, ok := m[key] |
||||
return ok |
||||
} |
@ -1,14 +0,0 @@
@@ -1,14 +0,0 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
Version 2, December 2004 |
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net> |
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified |
||||
copies of this license document, and changing it is allowed as long |
||||
as the name is changed. |
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE |
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION |
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO. |
||||
|
@ -1,21 +0,0 @@
@@ -1,21 +0,0 @@
|
||||
# TOML Validator |
||||
|
||||
If Go is installed, it's simple to try it out: |
||||
|
||||
```bash |
||||
go get github.com/BurntSushi/toml/cmd/tomlv |
||||
tomlv some-toml-file.toml |
||||
``` |
||||
|
||||
You can see the types of every key in a TOML file with: |
||||
|
||||
```bash |
||||
tomlv -types some-toml-file.toml |
||||
``` |
||||
|
||||
At the moment, only one error message is reported at a time. Error messages |
||||
include line numbers. No output means that the files given are valid TOML, or |
||||
there is a bug in `tomlv`. |
||||
|
||||
Compatible with TOML version |
||||
[v0.4.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.4.0.md) |
@ -1,61 +0,0 @@
@@ -1,61 +0,0 @@
|
||||
// Command tomlv validates TOML documents and prints each key's type.
|
||||
package main |
||||
|
||||
import ( |
||||
"flag" |
||||
"fmt" |
||||
"log" |
||||
"os" |
||||
"path" |
||||
"strings" |
||||
"text/tabwriter" |
||||
|
||||
"github.com/BurntSushi/toml" |
||||
) |
||||
|
||||
var ( |
||||
flagTypes = false |
||||
) |
||||
|
||||
func init() { |
||||
log.SetFlags(0) |
||||
|
||||
flag.BoolVar(&flagTypes, "types", flagTypes, |
||||
"When set, the types of every defined key will be shown.") |
||||
|
||||
flag.Usage = usage |
||||
flag.Parse() |
||||
} |
||||
|
||||
func usage() { |
||||
log.Printf("Usage: %s toml-file [ toml-file ... ]\n", |
||||
path.Base(os.Args[0])) |
||||
flag.PrintDefaults() |
||||
|
||||
os.Exit(1) |
||||
} |
||||
|
||||
func main() { |
||||
if flag.NArg() < 1 { |
||||
flag.Usage() |
||||
} |
||||
for _, f := range flag.Args() { |
||||
var tmp interface{} |
||||
md, err := toml.DecodeFile(f, &tmp) |
||||
if err != nil { |
||||
log.Fatalf("Error in '%s': %s", f, err) |
||||
} |
||||
if flagTypes { |
||||
printTypes(md) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func printTypes(md toml.MetaData) { |
||||
tabw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0) |
||||
for _, key := range md.Keys() { |
||||
fmt.Fprintf(tabw, "%s%s\t%s\n", |
||||
strings.Repeat(" ", len(key)-1), key, md.Type(key...)) |
||||
} |
||||
tabw.Flush() |
||||
} |
@ -1,509 +0,0 @@
@@ -1,509 +0,0 @@
|
||||
package toml |
||||
|
||||
import ( |
||||
"fmt" |
||||
"io" |
||||
"io/ioutil" |
||||
"math" |
||||
"reflect" |
||||
"strings" |
||||
"time" |
||||
) |
||||
|
||||
func e(format string, args ...interface{}) error { |
||||
return fmt.Errorf("toml: "+format, args...) |
||||
} |
||||
|
||||
// Unmarshaler is the interface implemented by objects that can unmarshal a
|
||||
// TOML description of themselves.
|
||||
type Unmarshaler interface { |
||||
UnmarshalTOML(interface{}) error |
||||
} |
||||
|
||||
// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
|
||||
func Unmarshal(p []byte, v interface{}) error { |
||||
_, err := Decode(string(p), v) |
||||
return err |
||||
} |
||||
|
||||
// Primitive is a TOML value that hasn't been decoded into a Go value.
|
||||
// When using the various `Decode*` functions, the type `Primitive` may
|
||||
// be given to any value, and its decoding will be delayed.
|
||||
//
|
||||
// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
|
||||
//
|
||||
// The underlying representation of a `Primitive` value is subject to change.
|
||||
// Do not rely on it.
|
||||
//
|
||||
// N.B. Primitive values are still parsed, so using them will only avoid
|
||||
// the overhead of reflection. They can be useful when you don't know the
|
||||
// exact type of TOML data until run time.
|
||||
type Primitive struct { |
||||
undecoded interface{} |
||||
context Key |
||||
} |
||||
|
||||
// DEPRECATED!
|
||||
//
|
||||
// Use MetaData.PrimitiveDecode instead.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error { |
||||
md := MetaData{decoded: make(map[string]bool)} |
||||
return md.unify(primValue.undecoded, rvalue(v)) |
||||
} |
||||
|
||||
// PrimitiveDecode is just like the other `Decode*` functions, except it
|
||||
// decodes a TOML value that has already been parsed. Valid primitive values
|
||||
// can *only* be obtained from values filled by the decoder functions,
|
||||
// including this method. (i.e., `v` may contain more `Primitive`
|
||||
// values.)
|
||||
//
|
||||
// Meta data for primitive values is included in the meta data returned by
|
||||
// the `Decode*` functions with one exception: keys returned by the Undecoded
|
||||
// method will only reflect keys that were decoded. Namely, any keys hidden
|
||||
// behind a Primitive will be considered undecoded. Executing this method will
|
||||
// update the undecoded keys in the meta data. (See the example.)
|
||||
func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error { |
||||
md.context = primValue.context |
||||
defer func() { md.context = nil }() |
||||
return md.unify(primValue.undecoded, rvalue(v)) |
||||
} |
||||
|
||||
// Decode will decode the contents of `data` in TOML format into a pointer
|
||||
// `v`.
|
||||
//
|
||||
// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
|
||||
// used interchangeably.)
|
||||
//
|
||||
// TOML arrays of tables correspond to either a slice of structs or a slice
|
||||
// of maps.
|
||||
//
|
||||
// TOML datetimes correspond to Go `time.Time` values.
|
||||
//
|
||||
// All other TOML types (float, string, int, bool and array) correspond
|
||||
// to the obvious Go types.
|
||||
//
|
||||
// An exception to the above rules is if a type implements the
|
||||
// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
|
||||
// (floats, strings, integers, booleans and datetimes) will be converted to
|
||||
// a byte string and given to the value's UnmarshalText method. See the
|
||||
// Unmarshaler example for a demonstration with time duration strings.
|
||||
//
|
||||
// Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go
|
||||
// struct. The special `toml` struct tag may be used to map TOML keys to
|
||||
// struct fields that don't match the key name exactly. (See the example.)
|
||||
// A case insensitive match to struct names will be tried if an exact match
|
||||
// can't be found.
|
||||
//
|
||||
// The mapping between TOML values and Go values is loose. That is, there
|
||||
// may exist TOML values that cannot be placed into your representation, and
|
||||
// there may be parts of your representation that do not correspond to
|
||||
// TOML values. This loose mapping can be made stricter by using the IsDefined
|
||||
// and/or Undecoded methods on the MetaData returned.
|
||||
//
|
||||
// This decoder will not handle cyclic types. If a cyclic type is passed,
|
||||
// `Decode` will not terminate.
|
||||
func Decode(data string, v interface{}) (MetaData, error) { |
||||
rv := reflect.ValueOf(v) |
||||
if rv.Kind() != reflect.Ptr { |
||||
return MetaData{}, e("Decode of non-pointer %s", reflect.TypeOf(v)) |
||||
} |
||||
if rv.IsNil() { |
||||
return MetaData{}, e("Decode of nil %s", reflect.TypeOf(v)) |
||||
} |
||||
p, err := parse(data) |
||||
if err != nil { |
||||
return MetaData{}, err |
||||
} |
||||
md := MetaData{ |
||||
p.mapping, p.types, p.ordered, |
||||
make(map[string]bool, len(p.ordered)), nil, |
||||
} |
||||
return md, md.unify(p.mapping, indirect(rv)) |
||||
} |
||||
|
||||
// DecodeFile is just like Decode, except it will automatically read the
|
||||
// contents of the file at `fpath` and decode it for you.
|
||||
func DecodeFile(fpath string, v interface{}) (MetaData, error) { |
||||
bs, err := ioutil.ReadFile(fpath) |
||||
if err != nil { |
||||
return MetaData{}, err |
||||
} |
||||
return Decode(string(bs), v) |
||||
} |
||||
|
||||
// DecodeReader is just like Decode, except it will consume all bytes
|
||||
// from the reader and decode it for you.
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) { |
||||
bs, err := ioutil.ReadAll(r) |
||||
if err != nil { |
||||
return MetaData{}, err |
||||
} |
||||
return Decode(string(bs), v) |
||||
} |
||||
|
||||
// unify performs a sort of type unification based on the structure of `rv`,
|
||||
// which is the client representation.
|
||||
//
|
||||
// Any type mismatch produces an error. Finding a type that we don't know
|
||||
// how to handle produces an unsupported type error.
|
||||
func (md *MetaData) unify(data interface{}, rv reflect.Value) error { |
||||
|
||||
// Special case. Look for a `Primitive` value.
|
||||
if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() { |
||||
// Save the undecoded data and the key context into the primitive
|
||||
// value.
|
||||
context := make(Key, len(md.context)) |
||||
copy(context, md.context) |
||||
rv.Set(reflect.ValueOf(Primitive{ |
||||
undecoded: data, |
||||
context: context, |
||||
})) |
||||
return nil |
||||
} |
||||
|
||||
// Special case. Unmarshaler Interface support.
|
||||
if rv.CanAddr() { |
||||
if v, ok := rv.Addr().Interface().(Unmarshaler); ok { |
||||
return v.UnmarshalTOML(data) |
||||
} |
||||
} |
||||
|
||||
// Special case. Handle time.Time values specifically.
|
||||
// TODO: Remove this code when we decide to drop support for Go 1.1.
|
||||
// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
|
||||
// interfaces.
|
||||
if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) { |
||||
return md.unifyDatetime(data, rv) |
||||
} |
||||
|
||||
// Special case. Look for a value satisfying the TextUnmarshaler interface.
|
||||
if v, ok := rv.Interface().(TextUnmarshaler); ok { |
||||
return md.unifyText(data, v) |
||||
} |
||||
// BUG(burntsushi)
|
||||
// The behavior here is incorrect whenever a Go type satisfies the
|
||||
// encoding.TextUnmarshaler interface but also corresponds to a TOML
|
||||
// hash or array. In particular, the unmarshaler should only be applied
|
||||
// to primitive TOML values. But at this point, it will be applied to
|
||||
// all kinds of values and produce an incorrect error whenever those values
|
||||
// are hashes or arrays (including arrays of tables).
|
||||
|
||||
k := rv.Kind() |
||||
|
||||
// laziness
|
||||
if k >= reflect.Int && k <= reflect.Uint64 { |
||||
return md.unifyInt(data, rv) |
||||
} |
||||
switch k { |
||||
case reflect.Ptr: |
||||
elem := reflect.New(rv.Type().Elem()) |
||||
err := md.unify(data, reflect.Indirect(elem)) |
||||
if err != nil { |
||||
return err |
||||
} |
||||
rv.Set(elem) |
||||
return nil |
||||
case reflect.Struct: |
||||
return md.unifyStruct(data, rv) |
||||
case reflect.Map: |
||||
return md.unifyMap(data, rv) |
||||
case reflect.Array: |
||||
return md.unifyArray(data, rv) |
||||
case reflect.Slice: |
||||
return md.unifySlice(data, rv) |
||||
case reflect.String: |
||||
return md.unifyString(data, rv) |
||||
case reflect.Bool: |
||||
return md.unifyBool(data, rv) |
||||
case reflect.Interface: |
||||
// we only support empty interfaces.
|
||||
if rv.NumMethod() > 0 { |
||||
return e("unsupported type %s", rv.Type()) |
||||
} |
||||
return md.unifyAnything(data, rv) |
||||
case reflect.Float32: |
||||
fallthrough |
||||
case reflect.Float64: |
||||
return md.unifyFloat64(data, rv) |
||||
} |
||||
return e("unsupported type %s", rv.Kind()) |
||||
} |
||||
|
||||
func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error { |
||||
tmap, ok := mapping.(map[string]interface{}) |
||||
if !ok { |
||||
if mapping == nil { |
||||
return nil |
||||
} |
||||
return e("type mismatch for %s: expected table but found %T", |
||||
rv.Type().String(), mapping) |
||||
} |
||||
|
||||
for key, datum := range tmap { |
||||
var f *field |
||||
fields := cachedTypeFields(rv.Type()) |
||||
for i := range fields { |
||||
ff := &fields[i] |
||||
if ff.name == key { |
||||
f = ff |
||||
break |
||||
} |
||||
if f == nil && strings.EqualFold(ff.name, key) { |
||||
f = ff |
||||
} |
||||
} |
||||
if f != nil { |
||||
subv := rv |
||||
for _, i := range f.index { |
||||
subv = indirect(subv.Field(i)) |
||||
} |
||||
if isUnifiable(subv) { |
||||
md.decoded[md.context.add(key).String()] = true |
||||
md.context = append(md.context, key) |
||||
if err := md.unify(datum, subv); err != nil { |
||||
return err |
||||
} |
||||
md.context = md.context[0 : len(md.context)-1] |
||||
} else if f.name != "" { |
||||
// Bad user! No soup for you!
|
||||
return e("cannot write unexported field %s.%s", |
||||
rv.Type().String(), f.name) |
||||
} |
||||
} |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error { |
||||
tmap, ok := mapping.(map[string]interface{}) |
||||
if !ok { |
||||
if tmap == nil { |
||||
return nil |
||||
} |
||||
return badtype("map", mapping) |
||||
} |
||||
if rv.IsNil() { |
||||
rv.Set(reflect.MakeMap(rv.Type())) |
||||
} |
||||
for k, v := range tmap { |
||||
md.decoded[md.context.add(k).String()] = true |
||||
md.context = append(md.context, k) |
||||
|
||||
rvkey := indirect(reflect.New(rv.Type().Key())) |
||||
rvval := reflect.Indirect(reflect.New(rv.Type().Elem())) |
||||
if err := md.unify(v, rvval); err != nil { |
||||
return err |
||||
} |
||||
md.context = md.context[0 : len(md.context)-1] |
||||
|
||||
rvkey.SetString(k) |
||||
rv.SetMapIndex(rvkey, rvval) |
||||
} |
||||
return nil |
||||
} |
||||
|
||||
func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error { |
||||
datav := reflect.ValueOf(data) |
||||
if datav.Kind() != reflect.Slice { |
||||
if !datav.IsValid() { |
||||
return nil |
||||
} |
||||