text: package toml
  
  import (
  	"fmt"
  	"log"
  	"math"
  	"reflect"
  	"strings"
  	"testing"
  	"time"
  )
  
  func TestDecodeSimple(t *testing.T) {
  	var testSimple = `
  age = 250
  andrew = "gallant"
  kait = "brady"
  now = 1987-07-05T05:45:00Z
  nowEast = 2017-06-22T16:15:21+08:00
  nowWest = 2017-06-22T02:14:36-06:00
  yesOrNo = true
  pi = 3.14
  colors = [
  	["red", "green", "blue"],
  	["cyan", "magenta", "yellow", "black"],
  ]
  
  [My.Cats]
  plato = "cat 1"
  cauchy = "cat 2"
  `
  
  	type cats struct {
  		Plato  string
  		Cauchy string
  	}
  	type simple struct {
  		Age     int
  		Colors  [][]string
  		Pi      float64
  		YesOrNo bool
  		Now     time.Time
  		NowEast time.Time
  		NowWest time.Time
  		Andrew  string
  		Kait    string
  		My      map[string]cats
  	}
  
  	var val simple
  	_, err := Decode(testSimple, &val)
  	if err != nil {
  		t.Fatal(err)
  	}
  
  	now, err := time.Parse("2006-01-02T15:04:05", "1987-07-05T05:45:00")
  	if err != nil {
  		panic(err)
  	}
  	nowEast, err := time.Parse("2006-01-02T15:04:05-07:00", "2017-06-22T16:15:21+08:00")
  	if err != nil {
  		panic(err)
  	}
  	nowWest, err := time.Parse("2006-01-02T15:04:05-07:00", "2017-06-22T02:14:36-06:00")
  	if err != nil {
  		panic(err)
  	}
  	var answer = simple{
  		Age:     250,
  		Andrew:  "gallant",
  		Kait:    "brady",
  		Now:     now,
  		NowEast: nowEast,
  		NowWest: nowWest,
  		YesOrNo: true,
  		Pi:      3.14,
  		Colors: [][]string{
  			{"red", "green", "blue"},
  			{"cyan", "magenta", "yellow", "black"},
  		},
  		My: map[string]cats{
  			"Cats": {Plato: "cat 1", Cauchy: "cat 2"},
  		},
  	}
  	if !reflect.DeepEqual(val, answer) {
  		t.Fatalf("Expected\n-----\n%#v\n-----\nbut got\n-----\n%#v\n",
  			answer, val)
  	}
  }
  
  func TestDecodeEmbedded(t *testing.T) {
  	type Dog struct{ Name string }
  	type Age int
  	type cat struct{ Name string }
  
  	for _, test := range []struct {
  		label       string
  		input       string
  		decodeInto  interface{}
  		wantDecoded interface{}
  	}{
  		{
  			label:       "embedded struct",
  			input:       `Name = "milton"`,
  			decodeInto:  &struct{ Dog }{},
  			wantDecoded: &struct{ Dog }{Dog{"milton"}},
  		},
  		{
  			label:       "embedded non-nil pointer to struct",
  			input:       `Name = "milton"`,
  			decodeInto:  &struct{ *Dog }{},
  			wantDecoded: &struct{ *Dog }{&Dog{"milton"}},
  		},
  		{
  			label:       "embedded nil pointer to struct",
  			input:       ``,
  			decodeInto:  &struct{ *Dog }{},
  			wantDecoded: &struct{ *Dog }{nil},
  		},
  		{
  			label:       "unexported embedded struct",
  			input:       `Name = "socks"`,
  			decodeInto:  &struct{ cat }{},
  			wantDecoded: &struct{ cat }{cat{"socks"}},
  		},
  		{
  			label:       "embedded int",
  			input:       `Age = -5`,
  			decodeInto:  &struct{ Age }{},
  			wantDecoded: &struct{ Age }{-5},
  		},
  	} {
  		_, err := Decode(test.input, test.decodeInto)
  		if err != nil {
  			t.Fatal(err)
  		}
  		if !reflect.DeepEqual(test.wantDecoded, test.decodeInto) {
  			t.Errorf("%s: want decoded == %+v, got %+v",
  				test.label, test.wantDecoded, test.decodeInto)
  		}
  	}
  }
  
  func TestDecodeIgnoredFields(t *testing.T) {
  	type simple struct {
  		Number int `toml:"-"`
  	}
  	const input = `
  Number = 123
  - = 234
  `
  	var s simple
  	if _, err := Decode(input, &s); err != nil {
  		t.Fatal(err)
  	}
  	if s.Number != 0 {
  		t.Errorf("got: %d; want 0", s.Number)
  	}
  }
  
  func TestTableArrays(t *testing.T) {
  	var tomlTableArrays = `
  [[albums]]
  name = "Born to Run"
  
    [[albums.songs]]
    name = "Jungleland"
  
    [[albums.songs]]
    name = "Meeting Across the River"
  
  [[albums]]
  name = "Born in the USA"
  
    [[albums.songs]]
    name = "Glory Days"
  
    [[albums.songs]]
    name = "Dancing in the Dark"
  `
  
  	type Song struct {
  		Name string
  	}
  
  	type Album struct {
  		Name  string
  		Songs []Song
  	}
  
  	type Music struct {
  		Albums []Album
  	}
  
  	expected := Music{[]Album{
  		{"Born to Run", []Song{{"Jungleland"}, {"Meeting Across the River"}}},
  		{"Born in the USA", []Song{{"Glory Days"}, {"Dancing in the Dark"}}},
  	}}
  	var got Music
  	if _, err := Decode(tomlTableArrays, &got); err != nil {
  		t.Fatal(err)
  	}
  	if !reflect.DeepEqual(expected, got) {
  		t.Fatalf("\n%#v\n!=\n%#v\n", expected, got)
  	}
  }
  
  func TestTableNesting(t *testing.T) {
  	for _, tt := range []struct {
  		t    string
  		want []string
  	}{
  		{"[a.b.c]", []string{"a", "b", "c"}},
  		{`[a."b.c"]`, []string{"a", "b.c"}},
  		{`[a.'b.c']`, []string{"a", "b.c"}},
  		{`[a.' b ']`, []string{"a", " b "}},
  		{"[ d.e.f ]", []string{"d", "e", "f"}},
  		{"[ g . h . i ]", []string{"g", "h", "i"}},
  		{`[ j . "ʞ" . 'l' ]`, []string{"j", "ʞ", "l"}},
  	} {
  		var m map[string]interface{}
  		if _, err := Decode(tt.t, &m); err != nil {
  			t.Errorf("Decode(%q): got error: %s", tt.t, err)
  			continue
  		}
  		if keys := extractNestedKeys(m); !reflect.DeepEqual(keys, tt.want) {
  			t.Errorf("Decode(%q): got nested keys %#v; want %#v",
  				tt.t, keys, tt.want)
  		}
  	}
  }
  
  func extractNestedKeys(v map[string]interface{}) []string {
  	var result []string
  	for {
  		if len(v) != 1 {
  			return result
  		}
  		for k, m := range v {
  			result = append(result, k)
  			var ok bool
  			v, ok = m.(map[string]interface{})
  			if !ok {
  				return result
  			}
  		}
  
  	}
  }
  
  // Case insensitive matching tests.
  // A bit more comprehensive than needed given the current implementation,
  // but implementations change.
  // Probably still missing demonstrations of some ugly corner cases regarding
  // case insensitive matching and multiple fields.
  func TestCase(t *testing.T) {
  	var caseToml = `
  tOpString = "string"
  tOpInt = 1
  tOpFloat = 1.1
  tOpBool = true
  tOpdate = 2006-01-02T15:04:05Z
  tOparray = [ "array" ]
  Match = "i should be in Match only"
  MatcH = "i should be in MatcH only"
  once = "just once"
  [nEst.eD]
  nEstedString = "another string"
  `
  
  	type InsensitiveEd struct {
  		NestedString string
  	}
  
  	type InsensitiveNest struct {
  		Ed InsensitiveEd
  	}
  
  	type Insensitive struct {
  		TopString string
  		TopInt    int
  		TopFloat  float64
  		TopBool   bool
  		TopDate   time.Time
  		TopArray  []string
  		Match     string
  		MatcH     string
  		Once      string
  		OncE      string
  		Nest      InsensitiveNest
  	}
  
  	tme, err := time.Parse(time.RFC3339, time.RFC3339[:len(time.RFC3339)-5])
  	if err != nil {
  		panic(err)
  	}
  	expected := Insensitive{
  		TopString: "string",
  		TopInt:    1,
  		TopFloat:  1.1,
  		TopBool:   true,
  		TopDate:   tme,
  		TopArray:  []string{"array"},
  		MatcH:     "i should be in MatcH only",
  		Match:     "i should be in Match only",
  		Once:      "just once",
  		OncE:      "",
  		Nest: InsensitiveNest{
  			Ed: InsensitiveEd{NestedString: "another string"},
  		},
  	}
  	var got Insensitive
  	if _, err := Decode(caseToml, &got); err != nil {
  		t.Fatal(err)
  	}
  	if !reflect.DeepEqual(expected, got) {
  		t.Fatalf("\n%#v\n!=\n%#v\n", expected, got)
  	}
  }
  
  func TestPointers(t *testing.T) {
  	type Object struct {
  		Type        string
  		Description string
  	}
  
  	type Dict struct {
  		NamedObject map[string]*Object
  		BaseObject  *Object
  		Strptr      *string
  		Strptrs     []*string
  	}
  	s1, s2, s3 := "blah", "abc", "def"
  	expected := &Dict{
  		Strptr:  &s1,
  		Strptrs: []*string{&s2, &s3},
  		NamedObject: map[string]*Object{
  			"foo": {"FOO", "fooooo!!!"},
  			"bar": {"BAR", "ba-ba-ba-ba-barrrr!!!"},
  		},
  		BaseObject: &Object{"BASE", "da base"},
  	}
  
  	ex1 := `
  Strptr = "blah"
  Strptrs = ["abc", "def"]
  
  [NamedObject.foo]
  Type = "FOO"
  Description = "fooooo!!!"
  
  [NamedObject.bar]
  Type = "BAR"
  Description = "ba-ba-ba-ba-barrrr!!!"
  
  [BaseObject]
  Type = "BASE"
  Description = "da base"
  `
  	dict := new(Dict)
  	_, err := Decode(ex1, dict)
  	if err != nil {
  		t.Errorf("Decode error: %v", err)
  	}
  	if !reflect.DeepEqual(expected, dict) {
  		t.Fatalf("\n%#v\n!=\n%#v\n", expected, dict)
  	}
  }
  
  func TestDecodeDatetime(t *testing.T) {
  	const noTimestamp = "2006-01-02T15:04:05"
  	for _, tt := range []struct {
  		s      string
  		t      string
  		format string
  	}{
  		{"1979-05-27T07:32:00Z", "1979-05-27T07:32:00Z", time.RFC3339},
  		{"1979-05-27T00:32:00-07:00", "1979-05-27T00:32:00-07:00", time.RFC3339},
  		{
  			"1979-05-27T00:32:00.999999-07:00",
  			"1979-05-27T00:32:00.999999-07:00",
  			time.RFC3339,
  		},
  		{"1979-05-27T07:32:00", "1979-05-27T07:32:00", noTimestamp},
  		{
  			"1979-05-27T00:32:00.999999",
  			"1979-05-27T00:32:00.999999",
  			noTimestamp,
  		},
  		{"1979-05-27", "1979-05-27T00:00:00", noTimestamp},
  	} {
  		var x struct{ D time.Time }
  		input := "d = " + tt.s
  		if _, err := Decode(input, &x); err != nil {
  			t.Errorf("Decode(%q): got error: %s", input, err)
  			continue
  		}
  		want, err := time.ParseInLocation(tt.format, tt.t, time.Local)
  		if err != nil {
  			panic(err)
  		}
  		if !x.D.Equal(want) {
  			t.Errorf("Decode(%q): got %s; want %s", input, x.D, want)
  		}
  	}
  }
  
  func TestDecodeBadDatetime(t *testing.T) {
  	var x struct{ T time.Time }
  	for _, s := range []string{
  		"123",
  		"2006-01-50T00:00:00Z",
  		"2006-01-30T00:00",
  		"2006-01-30T",
  	} {
  		input := "T = " + s
  		if _, err := Decode(input, &x); err == nil {
  			t.Errorf("Expected invalid DateTime error for %q", s)
  		}
  	}
  }
  
  func TestDecodeMultilineStrings(t *testing.T) {
  	var x struct {
  		S string
  	}
  	const s0 = `s = """
  a b \n c
  d e f
  """`
  	if _, err := Decode(s0, &x); err != nil {
  		t.Fatal(err)
  	}
  	if want := "a b \n c\nd e f\n"; x.S != want {
  		t.Errorf("got: %q; want: %q", x.S, want)
  	}
  	const s1 = `s = """a b c\
  """`
  	if _, err := Decode(s1, &x); err != nil {
  		t.Fatal(err)
  	}
  	if want := "a b c"; x.S != want {
  		t.Errorf("got: %q; want: %q", x.S, want)
  	}
  }
  
  type sphere struct {
  	Center [3]float64
  	Radius float64
  }
  
  func TestDecodeSimpleArray(t *testing.T) {
  	var s1 sphere
  	if _, err := Decode(`center = [0.0, 1.5, 0.0]`, &s1); err != nil {
  		t.Fatal(err)
  	}
  }
  
  func TestDecodeArrayWrongSize(t *testing.T) {
  	var s1 sphere
  	if _, err := Decode(`center = [0.1, 2.3]`, &s1); err == nil {
  		t.Fatal("Expected array type mismatch error")
  	}
  }
  
  func TestDecodeLargeIntoSmallInt(t *testing.T) {
  	type table struct {
  		Value int8
  	}
  	var tab table
  	if _, err := Decode(`value = 500`, &tab); err == nil {
  		t.Fatal("Expected integer out-of-bounds error.")
  	}
  }
  
  func TestDecodeSizedInts(t *testing.T) {
  	type table struct {
  		U8  uint8
  		U16 uint16
  		U32 uint32
  		U64 uint64
  		U   uint
  		I8  int8
  		I16 int16
  		I32 int32
  		I64 int64
  		I   int
  	}
  	answer := table{1, 1, 1, 1, 1, -1, -1, -1, -1, -1}
  	toml := `
  	u8 = 1
  	u16 = 1
  	u32 = 1
  	u64 = 1
  	u = 1
  	i8 = -1
  	i16 = -1
  	i32 = -1
  	i64 = -1
  	i = -1
  	`
  	var tab table
  	if _, err := Decode(toml, &tab); err != nil {
  		t.Fatal(err.Error())
  	}
  	if answer != tab {
  		t.Fatalf("Expected %#v but got %#v", answer, tab)
  	}
  }
  
  func TestDecodeInts(t *testing.T) {
  	for _, tt := range []struct {
  		s    string
  		want int64
  	}{
  		{"0", 0},
  		{"+99", 99},
  		{"-10", -10},
  		{"1_234_567", 1234567},
  		{"1_2_3_4", 1234},
  		{"-9_223_372_036_854_775_808", math.MinInt64},
  		{"9_223_372_036_854_775_807", math.MaxInt64},
  	} {
  		var x struct{ N int64 }
  		input := "n = " + tt.s
  		if _, err := Decode(input, &x); err != nil {
  			t.Errorf("Decode(%q): got error: %s", input, err)
  			continue
  		}
  		if x.N != tt.want {
  			t.Errorf("Decode(%q): got %d; want %d", input, x.N, tt.want)
  		}
  	}
  }
  
  func TestDecodeFloats(t *testing.T) {
  	for _, tt := range []struct {
  		s    string
  		want float64
  	}{
  		{"+1.0", 1},
  		{"3.1415", 3.1415},
  		{"-0.01", -0.01},
  		{"5e+22", 5e22},
  		{"1e6", 1e6},
  		{"-2E-2", -2e-2},
  		{"6.626e-34", 6.626e-34},
  		{"9_224_617.445_991_228_313", 9224617.445991228313},
  		{"9_876.54_32e1_0", 9876.5432e10},
  	} {
  		var x struct{ N float64 }
  		input := "n = " + tt.s
  		if _, err := Decode(input, &x); err != nil {
  			t.Errorf("Decode(%q): got error: %s", input, err)
  			continue
  		}
  		if x.N != tt.want {
  			t.Errorf("Decode(%q): got %f; want %f", input, x.N, tt.want)
  		}
  	}
  }
  
  func TestDecodeMalformedNumbers(t *testing.T) {
  	for _, tt := range []struct {
  		s    string
  		want string
  	}{
  		{"++99", "expected a digit"},
  		{"0..1", "must be followed by one or more digits"},
  		{"0.1.2", "Invalid float value"},
  		{"1e2.3", "Invalid float value"},
  		{"1e2e3", "Invalid float value"},
  		{"_123", "expected value"},
  		{"123_", "surrounded by digits"},
  		{"1._23", "surrounded by digits"},
  		{"1e__23", "surrounded by digits"},
  		{"123.", "must be followed by one or more digits"},
  		{"1.e2", "must be followed by one or more digits"},
  	} {
  		var x struct{ N interface{} }
  		input := "n = " + tt.s
  		_, err := Decode(input, &x)
  		if err == nil {
  			t.Errorf("Decode(%q): got nil, want error containing %q",
  				input, tt.want)
  			continue
  		}
  		if !strings.Contains(err.Error(), tt.want) {
  			t.Errorf("Decode(%q): got %q, want error containing %q",
  				input, err, tt.want)
  		}
  	}
  }
  
  func TestDecodeBadValues(t *testing.T) {
  	for _, tt := range []struct {
  		v    interface{}
  		want string
  	}{
  		{3, "non-pointer int"},
  		{(*int)(nil), "nil"},
  	} {
  		_, err := Decode(`x = 3`, tt.v)
  		if err == nil {
  			t.Errorf("Decode(%v): got nil; want error containing %q",
  				tt.v, tt.want)
  			continue
  		}
  		if !strings.Contains(err.Error(), tt.want) {
  			t.Errorf("Decode(%v): got %q; want error containing %q",
  				tt.v, err, tt.want)
  		}
  	}
  }
  
  func TestUnmarshaler(t *testing.T) {
  
  	var tomlBlob = `
  [dishes.hamboogie]
  name = "Hamboogie with fries"
  price = 10.99
  
  [[dishes.hamboogie.ingredients]]
  name = "Bread Bun"
  
  [[dishes.hamboogie.ingredients]]
  name = "Lettuce"
  
  [[dishes.hamboogie.ingredients]]
  name = "Real Beef Patty"
  
  [[dishes.hamboogie.ingredients]]
  name = "Tomato"
  
  [dishes.eggsalad]
  name = "Egg Salad with rice"
  price = 3.99
  
  [[dishes.eggsalad.ingredients]]
  name = "Egg"
  
  [[dishes.eggsalad.ingredients]]
  name = "Mayo"
  
  [[dishes.eggsalad.ingredients]]
  name = "Rice"
  `
  	m := &menu{}
  	if _, err := Decode(tomlBlob, m); err != nil {
  		t.Fatal(err)
  	}
  
  	if len(m.Dishes) != 2 {
  		t.Log("two dishes should be loaded with UnmarshalTOML()")
  		t.Errorf("expected %d but got %d", 2, len(m.Dishes))
  	}
  
  	eggSalad := m.Dishes["eggsalad"]
  	if _, ok := interface{}(eggSalad).(dish); !ok {
  		t.Errorf("expected a dish")
  	}
  
  	if eggSalad.Name != "Egg Salad with rice" {
  		t.Errorf("expected the dish to be named 'Egg Salad with rice'")
  	}
  
  	if len(eggSalad.Ingredients) != 3 {
  		t.Log("dish should be loaded with UnmarshalTOML()")
  		t.Errorf("expected %d but got %d", 3, len(eggSalad.Ingredients))
  	}
  
  	found := false
  	for _, i := range eggSalad.Ingredients {
  		if i.Name == "Rice" {
  			found = true
  			break
  		}
  	}
  	if !found {
  		t.Error("Rice was not loaded in UnmarshalTOML()")
  	}
  
  	// test on a value - must be passed as *
  	o := menu{}
  	if _, err := Decode(tomlBlob, &o); err != nil {
  		t.Fatal(err)
  	}
  
  }
  
  func TestDecodeInlineTable(t *testing.T) {
  	input := `
  [CookieJar]
  Types = {Chocolate = "yummy", Oatmeal = "best ever"}
  
  [Seasons]
  Locations = {NY = {Temp = "not cold", Rating = 4}, MI = {Temp = "freezing", Rating = 9}}
  `
  	type cookieJar struct {
  		Types map[string]string
  	}
  	type properties struct {
  		Temp   string
  		Rating int
  	}
  	type seasons struct {
  		Locations map[string]properties
  	}
  	type wrapper struct {
  		CookieJar cookieJar
  		Seasons   seasons
  	}
  	var got wrapper
  
  	meta, err := Decode(input, &got)
  	if err != nil {
  		t.Fatal(err)
  	}
  	want := wrapper{
  		CookieJar: cookieJar{
  			Types: map[string]string{
  				"Chocolate": "yummy",
  				"Oatmeal":   "best ever",
  			},
  		},
  		Seasons: seasons{
  			Locations: map[string]properties{
  				"NY": {
  					Temp:   "not cold",
  					Rating: 4,
  				},
  				"MI": {
  					Temp:   "freezing",
  					Rating: 9,
  				},
  			},
  		},
  	}
  	if !reflect.DeepEqual(got, want) {
  		t.Fatalf("after decode, got:\n\n%#v\n\nwant:\n\n%#v", got, want)
  	}
  	if len(meta.keys) != 12 {
  		t.Errorf("after decode, got %d meta keys; want 12", len(meta.keys))
  	}
  	if len(meta.types) != 12 {
  		t.Errorf("after decode, got %d meta types; want 12", len(meta.types))
  	}
  }
  
  func TestDecodeInlineTableArray(t *testing.T) {
  	type point struct {
  		X, Y, Z int
  	}
  	var got struct {
  		Points []point
  	}
  	// Example inline table array from the spec.
  	const in = `
  points = [ { x = 1, y = 2, z = 3 },
             { x = 7, y = 8, z = 9 },
             { x = 2, y = 4, z = 8 } ]
  
  `
  	if _, err := Decode(in, &got); err != nil {
  		t.Fatal(err)
  	}
  	want := []point{
  		{X: 1, Y: 2, Z: 3},
  		{X: 7, Y: 8, Z: 9},
  		{X: 2, Y: 4, Z: 8},
  	}
  	if !reflect.DeepEqual(got.Points, want) {
  		t.Errorf("got %#v; want %#v", got.Points, want)
  	}
  }
  
  func TestDecodeMalformedInlineTable(t *testing.T) {
  	for _, tt := range []struct {
  		s    string
  		want string
  	}{
  		{"{,}", "unexpected comma"},
  		{"{x = 3 y = 4}", "expected a comma or an inline table terminator"},
  		{"{x=3,,y=4}", "unexpected comma"},
  		{"{x=3,\ny=4}", "newlines not allowed"},
  		{"{x=3\n,y=4}", "newlines not allowed"},
  	} {
  		var x struct{ A map[string]int }
  		input := "a = " + tt.s
  		_, err := Decode(input, &x)
  		if err == nil {
  			t.Errorf("Decode(%q): got nil, want error containing %q",
  				input, tt.want)
  			continue
  		}
  		if !strings.Contains(err.Error(), tt.want) {
  			t.Errorf("Decode(%q): got %q, want error containing %q",
  				input, err, tt.want)
  		}
  	}
  }
  
  type menu struct {
  	Dishes map[string]dish
  }
  
  func (m *menu) UnmarshalTOML(p interface{}) error {
  	m.Dishes = make(map[string]dish)
  	data, _ := p.(map[string]interface{})
  	dishes := data["dishes"].(map[string]interface{})
  	for n, v := range dishes {
  		if d, ok := v.(map[string]interface{}); ok {
  			nd := dish{}
  			nd.UnmarshalTOML(d)
  			m.Dishes[n] = nd
  		} else {
  			return fmt.Errorf("not a dish")
  		}
  	}
  	return nil
  }
  
  type dish struct {
  	Name        string
  	Price       float32
  	Ingredients []ingredient
  }
  
  func (d *dish) UnmarshalTOML(p interface{}) error {
  	data, _ := p.(map[string]interface{})
  	d.Name, _ = data["name"].(string)
  	d.Price, _ = data["price"].(float32)
  	ingredients, _ := data["ingredients"].([]map[string]interface{})
  	for _, e := range ingredients {
  		n, _ := interface{}(e).(map[string]interface{})
  		name, _ := n["name"].(string)
  		i := ingredient{name}
  		d.Ingredients = append(d.Ingredients, i)
  	}
  	return nil
  }
  
  type ingredient struct {
  	Name string
  }
  
  func TestDecodeSlices(t *testing.T) {
  	type T struct {
  		S []string
  	}
  	for i, tt := range []struct {
  		v     T
  		input string
  		want  T
  	}{
  		{T{}, "", T{}},
  		{T{[]string{}}, "", T{[]string{}}},
  		{T{[]string{"a", "b"}}, "", T{[]string{"a", "b"}}},
  		{T{}, "S = []", T{[]string{}}},
  		{T{[]string{}}, "S = []", T{[]string{}}},
  		{T{[]string{"a", "b"}}, "S = []", T{[]string{}}},
  		{T{}, `S = ["x"]`, T{[]string{"x"}}},
  		{T{[]string{}}, `S = ["x"]`, T{[]string{"x"}}},
  		{T{[]string{"a", "b"}}, `S = ["x"]`, T{[]string{"x"}}},
  	} {
  		if _, err := Decode(tt.input, &tt.v); err != nil {
  			t.Errorf("[%d] %s", i, err)
  			continue
  		}
  		if !reflect.DeepEqual(tt.v, tt.want) {
  			t.Errorf("[%d] got %#v; want %#v", i, tt.v, tt.want)
  		}
  	}
  }
  
  func TestDecodePrimitive(t *testing.T) {
  	type S struct {
  		P Primitive
  	}
  	type T struct {
  		S []int
  	}
  	slicep := func(s []int) *[]int { return &s }
  	arrayp := func(a [2]int) *[2]int { return &a }
  	mapp := func(m map[string]int) *map[string]int { return &m }
  	for i, tt := range []struct {
  		v     interface{}
  		input string
  		want  interface{}
  	}{
  		// slices
  		{slicep(nil), "", slicep(nil)},
  		{slicep([]int{}), "", slicep([]int{})},
  		{slicep([]int{1, 2, 3}), "", slicep([]int{1, 2, 3})},
  		{slicep(nil), "P = [1,2]", slicep([]int{1, 2})},
  		{slicep([]int{}), "P = [1,2]", slicep([]int{1, 2})},
  		{slicep([]int{1, 2, 3}), "P = [1,2]", slicep([]int{1, 2})},
  
  		// arrays
  		{arrayp([2]int{2, 3}), "", arrayp([2]int{2, 3})},
  		{arrayp([2]int{2, 3}), "P = [3,4]", arrayp([2]int{3, 4})},
  
  		// maps
  		{mapp(nil), "", mapp(nil)},
  		{mapp(map[string]int{}), "", mapp(map[string]int{})},
  		{mapp(map[string]int{"a": 1}), "", mapp(map[string]int{"a": 1})},
  		{mapp(nil), "[P]\na = 2", mapp(map[string]int{"a": 2})},
  		{mapp(map[string]int{}), "[P]\na = 2", mapp(map[string]int{"a": 2})},
  		{mapp(map[string]int{"a": 1, "b": 3}), "[P]\na = 2", mapp(map[string]int{"a": 2, "b": 3})},
  
  		// structs
  		{&T{nil}, "[P]", &T{nil}},
  		{&T{[]int{}}, "[P]", &T{[]int{}}},
  		{&T{[]int{1, 2, 3}}, "[P]", &T{[]int{1, 2, 3}}},
  		{&T{nil}, "[P]\nS = [1,2]", &T{[]int{1, 2}}},
  		{&T{[]int{}}, "[P]\nS = [1,2]", &T{[]int{1, 2}}},
  		{&T{[]int{1, 2, 3}}, "[P]\nS = [1,2]", &T{[]int{1, 2}}},
  	} {
  		var s S
  		md, err := Decode(tt.input, &s)
  		if err != nil {
  			t.Errorf("[%d] Decode error: %s", i, err)
  			continue
  		}
  		if err := md.PrimitiveDecode(s.P, tt.v); err != nil {
  			t.Errorf("[%d] PrimitiveDecode error: %s", i, err)
  			continue
  		}
  		if !reflect.DeepEqual(tt.v, tt.want) {
  			t.Errorf("[%d] got %#v; want %#v", i, tt.v, tt.want)
  		}
  	}
  }
  
  func TestDecodeErrors(t *testing.T) {
  	for _, s := range []string{
  		`x="`,
  		`x='`,
  		`x='''`,
  
  		// Cases found by fuzzing in
  		// https://github.com/BurntSushi/toml/issues/155.
  		`""�`,   // used to panic with index out of range
  		`e="""`, // used to hang
  	} {
  		var x struct{}
  		_, err := Decode(s, &x)
  		if err == nil {
  			t.Errorf("Decode(%q): got nil error", s)
  		}
  	}
  }
  
  // Test for https://github.com/BurntSushi/toml/pull/166.
  func TestDecodeBoolArray(t *testing.T) {
  	for _, tt := range []struct {
  		s    string
  		got  interface{}
  		want interface{}
  	}{
  		{
  			"a = [true, false]",
  			&struct{ A []bool }{},
  			&struct{ A []bool }{[]bool{true, false}},
  		},
  		{
  			"a = {a = true, b = false}",
  			&struct{ A map[string]bool }{},
  			&struct{ A map[string]bool }{map[string]bool{"a": true, "b": false}},
  		},
  	} {
  		if _, err := Decode(tt.s, tt.got); err != nil {
  			t.Errorf("Decode(%q): %s", tt.s, err)
  			continue
  		}
  		if !reflect.DeepEqual(tt.got, tt.want) {
  			t.Errorf("Decode(%q): got %#v; want %#v", tt.s, tt.got, tt.want)
  		}
  	}
  }
  
  func ExampleMetaData_PrimitiveDecode() {
  	var md MetaData
  	var err error
  
  	var tomlBlob = `
  ranking = ["Springsteen", "J Geils"]
  
  [bands.Springsteen]
  started = 1973
  albums = ["Greetings", "WIESS", "Born to Run", "Darkness"]
  
  [bands."J Geils"]
  started = 1970
  albums = ["The J. Geils Band", "Full House", "Blow Your Face Out"]
  `
  
  	type band struct {
  		Started int
  		Albums  []string
  	}
  	type classics struct {
  		Ranking []string
  		Bands   map[string]Primitive
  	}
  
  	// Do the initial decode. Reflection is delayed on Primitive values.
  	var music classics
  	if md, err = Decode(tomlBlob, &music); err != nil {
  		log.Fatal(err)
  	}
  
  	// MetaData still includes information on Primitive values.
  	fmt.Printf("Is `bands.Springsteen` defined? %v\n",
  		md.IsDefined("bands", "Springsteen"))
  
  	// Decode primitive data into Go values.
  	for _, artist := range music.Ranking {
  		// A band is a primitive value, so we need to decode it to get a
  		// real `band` value.
  		primValue := music.Bands[artist]
  
  		var aBand band
  		if err = md.PrimitiveDecode(primValue, &aBand); err != nil {
  			log.Fatal(err)
  		}
  		fmt.Printf("%s started in %d.\n", artist, aBand.Started)
  	}
  	// Check to see if there were any fields left undecoded.
  	// Note that this won't be empty before decoding the Primitive value!
  	fmt.Printf("Undecoded: %q\n", md.Undecoded())
  
  	// Output:
  	// Is `bands.Springsteen` defined? true
  	// Springsteen started in 1973.
  	// J Geils started in 1970.
  	// Undecoded: []
  }
  
  func ExampleDecode() {
  	var tomlBlob = `
  # Some comments.
  [alpha]
  ip = "10.0.0.1"
  
  	[alpha.config]
  	Ports = [ 8001, 8002 ]
  	Location = "Toronto"
  	Created = 1987-07-05T05:45:00Z
  
  [beta]
  ip = "10.0.0.2"
  
  	[beta.config]
  	Ports = [ 9001, 9002 ]
  	Location = "New Jersey"
  	Created = 1887-01-05T05:55:00Z
  `
  
  	type serverConfig struct {
  		Ports    []int
  		Location string
  		Created  time.Time
  	}
  
  	type server struct {
  		IP     string       `toml:"ip,omitempty"`
  		Config serverConfig `toml:"config"`
  	}
  
  	type servers map[string]server
  
  	var config servers
  	if _, err := Decode(tomlBlob, &config); err != nil {
  		log.Fatal(err)
  	}
  
  	for _, name := range []string{"alpha", "beta"} {
  		s := config[name]
  		fmt.Printf("Server: %s (ip: %s) in %s created on %s\n",
  			name, s.IP, s.Config.Location,
  			s.Config.Created.Format("2006-01-02"))
  		fmt.Printf("Ports: %v\n", s.Config.Ports)
  	}
  
  	// Output:
  	// Server: alpha (ip: 10.0.0.1) in Toronto created on 1987-07-05
  	// Ports: [8001 8002]
  	// Server: beta (ip: 10.0.0.2) in New Jersey created on 1887-01-05
  	// Ports: [9001 9002]
  }
  
  type duration struct {
  	time.Duration
  }
  
  func (d *duration) UnmarshalText(text []byte) error {
  	var err error
  	d.Duration, err = time.ParseDuration(string(text))
  	return err
  }
  
  // Example Unmarshaler shows how to decode TOML strings into your own
  // custom data type.
  func Example_unmarshaler() {
  	blob := `
  [[song]]
  name = "Thunder Road"
  duration = "4m49s"
  
  [[song]]
  name = "Stairway to Heaven"
  duration = "8m03s"
  `
  	type song struct {
  		Name     string
  		Duration duration
  	}
  	type songs struct {
  		Song []song
  	}
  	var favorites songs
  	if _, err := Decode(blob, &favorites); err != nil {
  		log.Fatal(err)
  	}
  
  	// Code to implement the TextUnmarshaler interface for `duration`:
  	//
  	// type duration struct {
  	// 	time.Duration
  	// }
  	//
  	// func (d *duration) UnmarshalText(text []byte) error {
  	// 	var err error
  	// 	d.Duration, err = time.ParseDuration(string(text))
  	// 	return err
  	// }
  
  	for _, s := range favorites.Song {
  		fmt.Printf("%s (%s)\n", s.Name, s.Duration)
  	}
  	// Output:
  	// Thunder Road (4m49s)
  	// Stairway to Heaven (8m3s)
  }
  
  // Example StrictDecoding shows how to detect whether there are keys in the
  // TOML document that weren't decoded into the value given. This is useful
  // for returning an error to the user if they've included extraneous fields
  // in their configuration.
  func Example_strictDecoding() {
  	var blob = `
  key1 = "value1"
  key2 = "value2"
  key3 = "value3"
  `
  	type config struct {
  		Key1 string
  		Key3 string
  	}
  
  	var conf config
  	md, err := Decode(blob, &conf)
  	if err != nil {
  		log.Fatal(err)
  	}
  	fmt.Printf("Undecoded keys: %q\n", md.Undecoded())
  	// Output:
  	// Undecoded keys: ["key2"]
  }
  
  // Example UnmarshalTOML shows how to implement a struct type that knows how to
  // unmarshal itself. The struct must take full responsibility for mapping the
  // values passed into the struct. The method may be used with interfaces in a
  // struct in cases where the actual type is not known until the data is
  // examined.
  func Example_unmarshalTOML() {
  
  	var blob = `
  [[parts]]
  type = "valve"
  id = "valve-1"
  size = 1.2
  rating = 4
  
  [[parts]]
  type = "valve"
  id = "valve-2"
  size = 2.1
  rating = 5
  
  [[parts]]
  type = "pipe"
  id = "pipe-1"
  length = 2.1
  diameter = 12
  
  [[parts]]
  type = "cable"
  id = "cable-1"
  length = 12
  rating = 3.1
  `
  	o := &order{}
  	err := Unmarshal([]byte(blob), o)
  	if err != nil {
  		log.Fatal(err)
  	}
  
  	fmt.Println(len(o.parts))
  
  	for _, part := range o.parts {
  		fmt.Println(part.Name())
  	}
  
  	// Code to implement UmarshalJSON.
  
  	// type order struct {
  	// 	// NOTE `order.parts` is a private slice of type `part` which is an
  	// 	// interface and may only be loaded from toml using the
  	// 	// UnmarshalTOML() method of the Umarshaler interface.
  	// 	parts parts
  	// }
  
  	// func (o *order) UnmarshalTOML(data interface{}) error {
  
  	// 	// NOTE the example below contains detailed type casting to show how
  	// 	// the 'data' is retrieved. In operational use, a type cast wrapper
  	// 	// may be preferred e.g.
  	// 	//
  	// 	// func AsMap(v interface{}) (map[string]interface{}, error) {
  	// 	// 		return v.(map[string]interface{})
  	// 	// }
  	// 	//
  	// 	// resulting in:
  	// 	// d, _ := AsMap(data)
  	// 	//
  
  	// 	d, _ := data.(map[string]interface{})
  	// 	parts, _ := d["parts"].([]map[string]interface{})
  
  	// 	for _, p := range parts {
  
  	// 		typ, _ := p["type"].(string)
  	// 		id, _ := p["id"].(string)
  
  	// 		// detect the type of part and handle each case
  	// 		switch p["type"] {
  	// 		case "valve":
  
  	// 			size := float32(p["size"].(float64))
  	// 			rating := int(p["rating"].(int64))
  
  	// 			valve := &valve{
  	// 				Type:   typ,
  	// 				ID:     id,
  	// 				Size:   size,
  	// 				Rating: rating,
  	// 			}
  
  	// 			o.parts = append(o.parts, valve)
  
  	// 		case "pipe":
  
  	// 			length := float32(p["length"].(float64))
  	// 			diameter := int(p["diameter"].(int64))
  
  	// 			pipe := &pipe{
  	// 				Type:     typ,
  	// 				ID:       id,
  	// 				Length:   length,
  	// 				Diameter: diameter,
  	// 			}
  
  	// 			o.parts = append(o.parts, pipe)
  
  	// 		case "cable":
  
  	// 			length := int(p["length"].(int64))
  	// 			rating := float32(p["rating"].(float64))
  
  	// 			cable := &cable{
  	// 				Type:   typ,
  	// 				ID:     id,
  	// 				Length: length,
  	// 				Rating: rating,
  	// 			}
  
  	// 			o.parts = append(o.parts, cable)
  
  	// 		}
  	// 	}
  
  	// 	return nil
  	// }
  
  	// type parts []part
  
  	// type part interface {
  	// 	Name() string
  	// }
  
  	// type valve struct {
  	// 	Type   string
  	// 	ID     string
  	// 	Size   float32
  	// 	Rating int
  	// }
  
  	// func (v *valve) Name() string {
  	// 	return fmt.Sprintf("VALVE: %s", v.ID)
  	// }
  
  	// type pipe struct {
  	// 	Type     string
  	// 	ID       string
  	// 	Length   float32
  	// 	Diameter int
  	// }
  
  	// func (p *pipe) Name() string {
  	// 	return fmt.Sprintf("PIPE: %s", p.ID)
  	// }
  
  	// type cable struct {
  	// 	Type   string
  	// 	ID     string
  	// 	Length int
  	// 	Rating float32
  	// }
  
  	// func (c *cable) Name() string {
  	// 	return fmt.Sprintf("CABLE: %s", c.ID)
  	// }
  
  	// Output:
  	// 4
  	// VALVE: valve-1
  	// VALVE: valve-2
  	// PIPE: pipe-1
  	// CABLE: cable-1
  
  }
  
  type order struct {
  	// NOTE `order.parts` is a private slice of type `part` which is an
  	// interface and may only be loaded from toml using the UnmarshalTOML()
  	// method of the Umarshaler interface.
  	parts parts
  }
  
  func (o *order) UnmarshalTOML(data interface{}) error {
  
  	// NOTE the example below contains detailed type casting to show how
  	// the 'data' is retrieved. In operational use, a type cast wrapper
  	// may be preferred e.g.
  	//
  	// func AsMap(v interface{}) (map[string]interface{}, error) {
  	// 		return v.(map[string]interface{})
  	// }
  	//
  	// resulting in:
  	// d, _ := AsMap(data)
  	//
  
  	d, _ := data.(map[string]interface{})
  	parts, _ := d["parts"].([]map[string]interface{})
  
  	for _, p := range parts {
  
  		typ, _ := p["type"].(string)
  		id, _ := p["id"].(string)
  
  		// detect the type of part and handle each case
  		switch p["type"] {
  		case "valve":
  
  			size := float32(p["size"].(float64))
  			rating := int(p["rating"].(int64))
  
  			valve := &valve{
  				Type:   typ,
  				ID:     id,
  				Size:   size,
  				Rating: rating,
  			}
  
  			o.parts = append(o.parts, valve)
  
  		case "pipe":
  
  			length := float32(p["length"].(float64))
  			diameter := int(p["diameter"].(int64))
  
  			pipe := &pipe{
  				Type:     typ,
  				ID:       id,
  				Length:   length,
  				Diameter: diameter,
  			}
  
  			o.parts = append(o.parts, pipe)
  
  		case "cable":
  
  			length := int(p["length"].(int64))
  			rating := float32(p["rating"].(float64))
  
  			cable := &cable{
  				Type:   typ,
  				ID:     id,
  				Length: length,
  				Rating: rating,
  			}
  
  			o.parts = append(o.parts, cable)
  
  		}
  	}
  
  	return nil
  }
  
  type parts []part
  
  type part interface {
  	Name() string
  }
  
  type valve struct {
  	Type   string
  	ID     string
  	Size   float32
  	Rating int
  }
  
  func (v *valve) Name() string {
  	return fmt.Sprintf("VALVE: %s", v.ID)
  }
  
  type pipe struct {
  	Type     string
  	ID       string
  	Length   float32
  	Diameter int
  }
  
  func (p *pipe) Name() string {
  	return fmt.Sprintf("PIPE: %s", p.ID)
  }
  
  type cable struct {
  	Type   string
  	ID     string
  	Length int
  	Rating float32
  }
  
  func (c *cable) Name() string {
  	return fmt.Sprintf("CABLE: %s", c.ID)
  }
  