1package csvutil
2
3import (
4	"bytes"
5	"encoding/base64"
6	"encoding/csv"
7	"encoding/json"
8	"errors"
9	"fmt"
10	"io"
11	"math"
12	"reflect"
13	"strconv"
14	"strings"
15	"testing"
16	"unicode"
17)
18
19var Binary = []byte("binary-data")
20
21var EncodedBinary = base64.StdEncoding.EncodeToString(Binary)
22
23var BinaryLarge = bytes.Repeat([]byte("1"), 128*1024)
24
25var EncodedBinaryLarge = base64.StdEncoding.EncodeToString(BinaryLarge)
26
27type Float float64
28
29type Enum uint8
30
31const (
32	EnumDefault = iota
33	EnumFirst
34	EnumSecond
35)
36
37func (e Enum) MarshalCSV() ([]byte, error) {
38	switch e {
39	case EnumFirst:
40		return []byte("first"), nil
41	case EnumSecond:
42		return []byte("second"), nil
43	default:
44		return []byte("default"), nil
45	}
46}
47
48func (e *Enum) UnmarshalCSV(data []byte) error {
49	s := string(data)
50	switch s {
51	case "first":
52		*e = EnumFirst
53	case "second":
54		*e = EnumSecond
55	default:
56		*e = EnumDefault
57	}
58	return nil
59}
60
61type ValueRecUnmarshaler struct {
62	S *string
63}
64
65func (u ValueRecUnmarshaler) UnmarshalCSV(data []byte) error {
66	*u.S = string(data)
67	return nil
68}
69
70func (u ValueRecUnmarshaler) Scan(data []byte) error {
71	*u.S = "scan: "
72	*u.S += string(data)
73	return nil
74}
75
76type ValueRecTextUnmarshaler struct {
77	S *string
78}
79
80func (u ValueRecTextUnmarshaler) UnmarshalText(text []byte) error {
81	*u.S = string(text)
82	return nil
83}
84
85type IntStruct struct {
86	Value int
87}
88
89func (i *IntStruct) Scan(state fmt.ScanState, verb rune) error {
90	switch verb {
91	case 'd', 'v':
92	default:
93		return errors.New("unsupported verb")
94	}
95
96	t, err := state.Token(false, unicode.IsDigit)
97	if err != nil {
98		return err
99	}
100
101	n, err := strconv.Atoi(string(t))
102	if err != nil {
103		return err
104	}
105	*i = IntStruct{Value: n}
106	return nil
107}
108
109type EnumType struct {
110	Enum Enum `csv:"enum"`
111}
112
113type Embedded1 struct {
114	String string  `csv:"string"`
115	Float  float64 `csv:"float"`
116}
117
118type Embedded2 struct {
119	Float float64 `csv:"float"`
120	Bool  bool    `csv:"bool"`
121}
122
123type Embedded3 map[string]string
124
125func (e *Embedded3) UnmarshalCSV(s []byte) error {
126	return json.Unmarshal(s, e)
127}
128
129func (e Embedded3) MarshalCSV() ([]byte, error) {
130	return json.Marshal(e)
131}
132
133type Embedded4 interface{}
134
135type Embedded5 struct {
136	Embedded6
137	Embedded7
138	Embedded8
139}
140
141type Embedded6 struct {
142	X int
143}
144
145type Embedded7 Embedded6
146
147type Embedded8 struct {
148	Embedded9
149}
150
151type Embedded9 struct {
152	X int
153	Y int
154}
155
156type Embedded10 struct {
157	Embedded11
158	Embedded12
159	Embedded13
160}
161
162type Embedded11 struct {
163	Embedded6
164}
165
166type Embedded12 struct {
167	Embedded6
168}
169
170type Embedded13 struct {
171	Embedded8
172}
173
174type Embedded17 struct {
175	*Embedded18
176}
177
178type Embedded18 struct {
179	X *float64
180	Y *float64
181}
182
183type TypeA struct {
184	Embedded1
185	String string `csv:"string"`
186	Embedded2
187	Int int `csv:"int"`
188}
189
190type TypeB struct {
191	Embedded3 `csv:"json"`
192	String    string `csv:"string"`
193}
194
195type TypeC struct {
196	*Embedded1
197	String string `csv:"string"`
198}
199
200type TypeD struct {
201	*Embedded3 `csv:"json"`
202	String     string `csv:"string"`
203}
204
205type TypeE struct {
206	String **string `csv:"string"`
207	Int    *int     `csv:"int"`
208}
209
210type TypeF struct {
211	Int      int          `csv:"int" custom:"int"`
212	Pint     *int         `csv:"pint" custom:"pint"`
213	Int8     int8         `csv:"int8" custom:"int8"`
214	Pint8    *int8        `csv:"pint8" custom:"pint8"`
215	Int16    int16        `csv:"int16" custom:"int16"`
216	Pint16   *int16       `csv:"pint16" custom:"pint16"`
217	Int32    int32        `csv:"int32" custom:"int32"`
218	Pint32   *int32       `csv:"pint32" custom:"pint32"`
219	Int64    int64        `csv:"int64" custom:"int64"`
220	Pint64   *int64       `csv:"pint64" custom:"pint64"`
221	UInt     uint         `csv:"uint" custom:"uint"`
222	Puint    *uint        `csv:"puint" custom:"puint"`
223	Uint8    uint8        `csv:"uint8" custom:"uint8"`
224	Puint8   *uint8       `csv:"puint8" custom:"puint8"`
225	Uint16   uint16       `csv:"uint16" custom:"uint16"`
226	Puint16  *uint16      `csv:"puint16" custom:"puint16"`
227	Uint32   uint32       `csv:"uint32" custom:"uint32"`
228	Puint32  *uint32      `csv:"puint32" custom:"puint32"`
229	Uint64   uint64       `csv:"uint64" custom:"uint64"`
230	Puint64  *uint64      `csv:"puint64" custom:"puint64"`
231	Float32  float32      `csv:"float32" custom:"float32"`
232	Pfloat32 *float32     `csv:"pfloat32" custom:"pfloat32"`
233	Float64  float64      `csv:"float64" custom:"float64"`
234	Pfloat64 *float64     `csv:"pfloat64" custom:"pfloat64"`
235	String   string       `csv:"string" custom:"string"`
236	PString  *string      `csv:"pstring" custom:"pstring"`
237	Bool     bool         `csv:"bool" custom:"bool"`
238	Pbool    *bool        `csv:"pbool" custom:"pbool"`
239	V        interface{}  `csv:"interface" custom:"interface"`
240	Pv       *interface{} `csv:"pinterface" custom:"pinterface"`
241	Binary   []byte       `csv:"binary" custom:"binary"`
242	PBinary  *[]byte      `csv:"pbinary" custom:"pbinary"`
243}
244
245type TypeG struct {
246	String      string
247	Int         int
248	Float       float64 `csv:"-"`
249	unexported1 int
250	unexported2 int `csv:"unexported2"`
251}
252
253type TypeI struct {
254	String string `csv:",omitempty"`
255	Int    int    `csv:"int,omitempty"`
256}
257
258type TypeK struct {
259	*TypeL
260}
261
262type TypeL struct {
263	String string
264	Int    int `csv:",omitempty"`
265}
266
267type Unmarshalers struct {
268	CSVUnmarshaler      CSVUnmarshaler      `csv:"csv"`
269	PCSVUnmarshaler     *CSVUnmarshaler     `csv:"pcsv"`
270	TextUnmarshaler     TextUnmarshaler     `csv:"text"`
271	PTextUnmarshaler    *TextUnmarshaler    `csv:"ptext"`
272	CSVTextUnmarshaler  CSVTextUnmarshaler  `csv:"csv-text"`
273	PCSVTextUnmarshaler *CSVTextUnmarshaler `csv:"pcsv-text"`
274}
275
276type EmbeddedUnmarshalers struct {
277	CSVUnmarshaler     `csv:"csv"`
278	TextUnmarshaler    `csv:"text"`
279	CSVTextUnmarshaler `csv:"csv-text"`
280}
281
282type EmbeddedPtrUnmarshalers struct {
283	*CSVUnmarshaler     `csv:"csv"`
284	*TextUnmarshaler    `csv:"text"`
285	*CSVTextUnmarshaler `csv:"csv-text"`
286}
287
288type CSVUnmarshaler struct {
289	String string `csv:"string"`
290}
291
292func (t *CSVUnmarshaler) UnmarshalCSV(s []byte) error {
293	t.String = "unmarshalCSV:" + string(s)
294	return nil
295}
296
297type TextUnmarshaler struct {
298	String string `csv:"string"`
299}
300
301func (t *TextUnmarshaler) UnmarshalText(text []byte) error {
302	t.String = "unmarshalText:" + string(text)
303	return nil
304}
305
306type CSVTextUnmarshaler struct {
307	String string `csv:"string"`
308}
309
310func (t *CSVTextUnmarshaler) UnmarshalCSV(s []byte) error {
311	t.String = "unmarshalCSV:" + string(s)
312	return nil
313}
314
315func (t *CSVTextUnmarshaler) UnmarshalText(text []byte) error {
316	t.String = "unmarshalText:" + string(text)
317	return nil
318}
319
320type TypeWithInvalidField struct {
321	String TypeI `csv:"string"`
322}
323
324type InvalidType struct {
325	String struct{}
326}
327
328type TagPriority struct {
329	Foo int
330	Bar int `csv:"Foo"`
331}
332
333type embedded struct {
334	Foo int `csv:"foo"`
335	bar int `csv:"bar"`
336}
337
338type UnexportedEmbedded struct {
339	embedded
340}
341
342type UnexportedEmbeddedPtr struct {
343	*embedded
344}
345
346type A struct {
347	B
348	X int
349}
350
351type B struct {
352	*A
353	Y int
354}
355
356var Int = 10
357var String = "string"
358var PString = &String
359var TypeISlice []TypeI
360
361func pint(n int) *int                       { return &n }
362func pint8(n int8) *int8                    { return &n }
363func pint16(n int16) *int16                 { return &n }
364func pint32(n int32) *int32                 { return &n }
365func pint64(n int64) *int64                 { return &n }
366func puint(n uint) *uint                    { return &n }
367func puint8(n uint8) *uint8                 { return &n }
368func puint16(n uint16) *uint16              { return &n }
369func puint32(n uint32) *uint32              { return &n }
370func puint64(n uint64) *uint64              { return &n }
371func pfloat32(f float32) *float32           { return &f }
372func pfloat64(f float64) *float64           { return &f }
373func pstring(s string) *string              { return &s }
374func pbool(b bool) *bool                    { return &b }
375func pinterface(v interface{}) *interface{} { return &v }
376
377func ppint(n int) **int       { p := pint(n); return &p }
378func pppint(n int) ***int     { p := ppint(n); return &p }
379func ppTypeI(v TypeI) **TypeI { p := &v; return &p }
380
381func TestDecoder(t *testing.T) {
382	fixtures := []struct {
383		desc           string
384		in             string
385		regFuncs       []interface{}
386		out            interface{}
387		expected       interface{}
388		expectedRecord []string
389		inheader       []string
390		header         []string
391		unused         []int
392		err            error
393	}{
394		{
395			desc: "embedded type - no tag - conflicting float tag",
396			in:   "string,int,float,bool\nstring,5,2.5,t",
397			out:  &TypeA{},
398			expected: &TypeA{
399				Embedded1: Embedded1{},
400				Embedded2: Embedded2{Bool: true},
401				String:    "string",
402				Int:       5,
403			},
404			unused:         []int{2},
405			expectedRecord: []string{"string", "5", "2.5", "t"},
406			header:         []string{"string", "int", "float", "bool"},
407		},
408		{
409			desc: "embedded type - with tag",
410			in: `string,json
411string,"{""key"":""value""}"
412`,
413			out: &TypeB{},
414			expected: &TypeB{
415				Embedded3: Embedded3{"key": "value"},
416				String:    "string",
417			},
418			expectedRecord: []string{"string", `{"key":"value"}`},
419			header:         []string{"string", "json"},
420		},
421		{
422			desc: "embedded pointer type - no tag - type with conflicting tag",
423			in:   "string,float\nstring,2.5",
424			out:  &TypeC{},
425			expected: &TypeC{
426				Embedded1: &Embedded1{Float: 2.5},
427				String:    "string",
428			},
429			expectedRecord: []string{"string", "2.5"},
430			header:         []string{"string", "float"},
431		},
432		{
433			desc: "embedded pointer type - with tag ",
434			in: `string,json
435string,"{""key"":""value""}"
436`,
437			out: &TypeD{},
438			expected: &TypeD{
439				Embedded3: &Embedded3{"key": "value"},
440				String:    "string",
441			},
442			expectedRecord: []string{"string", `{"key":"value"}`},
443			header:         []string{"string", "json"},
444		},
445		{
446			desc: "pointer types",
447			in:   "string,int\nstring,10",
448			out:  &TypeE{},
449			expected: &TypeE{
450				String: &PString,
451				Int:    &Int,
452			},
453			expectedRecord: []string{"string", "10"},
454			header:         []string{"string", "int"},
455		},
456		{
457			desc: "basic types",
458			in: "int,pint,int8,pint8,int16,pint16,int32,pint32,int64,pint64,uint," +
459				"puint,uint8,puint8,uint16,puint16,uint32,puint32,uint64,puint64,float32," +
460				"pfloat32,float64,pfloat64,string,pstring,bool,pbool,interface,pinterface,binary,pbinary\n" +
461				"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,true,true,true,1," +
462				EncodedBinary + "," + EncodedBinaryLarge,
463			out: &TypeF{},
464			expected: &TypeF{
465				Int:      1,
466				Pint:     pint(2),
467				Int8:     3,
468				Pint8:    pint8(4),
469				Int16:    5,
470				Pint16:   pint16(6),
471				Int32:    7,
472				Pint32:   pint32(8),
473				Int64:    9,
474				Pint64:   pint64(10),
475				UInt:     11,
476				Puint:    puint(12),
477				Uint8:    13,
478				Puint8:   puint8(14),
479				Uint16:   15,
480				Puint16:  puint16(16),
481				Uint32:   17,
482				Puint32:  puint32(18),
483				Uint64:   19,
484				Puint64:  puint64(20),
485				Float32:  21,
486				Pfloat32: pfloat32(22),
487				Float64:  23,
488				Pfloat64: pfloat64(24),
489				String:   "25",
490				PString:  pstring("26"),
491				Bool:     true,
492				Pbool:    pbool(true),
493				V:        "true",
494				Pv:       pinterface("1"),
495				Binary:   Binary,
496				PBinary:  &BinaryLarge,
497			},
498			expectedRecord: []string{"1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12",
499				"13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26",
500				"true", "true", "true", "1", EncodedBinary, EncodedBinaryLarge},
501			header: []string{"int",
502				"pint",
503				"int8",
504				"pint8",
505				"int16",
506				"pint16",
507				"int32",
508				"pint32",
509				"int64",
510				"pint64",
511				"uint",
512				"puint",
513				"uint8",
514				"puint8",
515				"uint16",
516				"puint16",
517				"uint32",
518				"puint32",
519				"uint64",
520				"puint64",
521				"float32",
522				"pfloat32",
523				"float64",
524				"pfloat64",
525				"string",
526				"pstring",
527				"bool",
528				"pbool",
529				"interface",
530				"pinterface",
531				"binary",
532				"pbinary",
533			},
534		},
535		{
536			desc: "tags and unexported fields",
537			in:   "String,int,Float64,unexported1,unexported2\nstring,10,2.5,1,1",
538			out:  &TypeG{},
539			expected: &TypeG{
540				String: "string",
541			},
542			expectedRecord: []string{"string", "10", "2.5", "1", "1"},
543			unused:         []int{1, 2, 3, 4},
544			header:         []string{"String", "int", "Float64", "unexported1", "unexported2"},
545		},
546		{
547			desc:           "omitempty tag",
548			in:             "String,int\n,",
549			out:            &TypeI{},
550			expected:       &TypeI{},
551			expectedRecord: []string{"", ""},
552			header:         []string{"String", "int"},
553		},
554		{
555			desc:           "empty struct",
556			in:             "String\n1",
557			out:            &struct{}{},
558			expected:       &struct{}{},
559			expectedRecord: []string{"1"},
560			header:         []string{"String"},
561			unused:         []int{0},
562		},
563		{
564			desc: "decode value receiver unmarshalers",
565			in:   "1,2,3\n1,2,3",
566			out: &struct {
567				ValueRecUnmarshaler    ValueRecUnmarshaler  `csv:"1"`
568				PtrValueRecUnmarshaler *ValueRecUnmarshaler `csv:"2"`
569				Iface                  interface{}          `csv:"3"`
570			}{
571				ValueRecUnmarshaler{new(string)},
572				&ValueRecUnmarshaler{new(string)},
573				ValueRecUnmarshaler{new(string)},
574			},
575			expected: &struct {
576				ValueRecUnmarshaler    ValueRecUnmarshaler  `csv:"1"`
577				PtrValueRecUnmarshaler *ValueRecUnmarshaler `csv:"2"`
578				Iface                  interface{}          `csv:"3"`
579			}{
580				ValueRecUnmarshaler{pstring("1")},
581				&ValueRecUnmarshaler{pstring("2")},
582				ValueRecUnmarshaler{pstring("3")},
583			},
584			expectedRecord: []string{"1", "2", "3"},
585			header:         []string{"1", "2", "3"},
586		},
587		{
588			desc: "decode value receiver registered func",
589			in:   "1,2,3,4\n1,2,3,4",
590			out: &struct {
591				ValueRecUnmarshaler    ValueRecUnmarshaler  `csv:"1"`
592				PtrValueRecUnmarshaler *ValueRecUnmarshaler `csv:"2"`
593				Iface                  interface{}          `csv:"3"`
594				Iface2                 interface{}          `csv:"4"`
595			}{
596				ValueRecUnmarshaler{new(string)},
597				&ValueRecUnmarshaler{new(string)},
598				ValueRecUnmarshaler{new(string)},
599				&ValueRecUnmarshaler{new(string)},
600			},
601			expected: &struct {
602				ValueRecUnmarshaler    ValueRecUnmarshaler  `csv:"1"`
603				PtrValueRecUnmarshaler *ValueRecUnmarshaler `csv:"2"`
604				Iface                  interface{}          `csv:"3"`
605				Iface2                 interface{}          `csv:"4"`
606			}{
607				ValueRecUnmarshaler{pstring("scan: 1")},
608				&ValueRecUnmarshaler{pstring("scan: 2")},
609				ValueRecUnmarshaler{pstring("scan: 3")},
610				&ValueRecUnmarshaler{pstring("scan: 4")},
611			},
612			regFuncs: []interface{}{
613				func(data []byte, v ValueRecUnmarshaler) error {
614					return v.Scan(data)
615				},
616			},
617			expectedRecord: []string{"1", "2", "3", "4"},
618			header:         []string{"1", "2", "3", "4"},
619		},
620		{
621			desc: "decode value receiver registered func - T is interface",
622			in:   "1,2,3,4\n1,2,3,4",
623			out: &struct {
624				ValueRecUnmarshaler    ValueRecUnmarshaler  `csv:"1"`
625				PtrValueRecUnmarshaler *ValueRecUnmarshaler `csv:"2"`
626				Iface                  interface{}          `csv:"3"`
627				Iface2                 interface{}          `csv:"4"`
628			}{
629				ValueRecUnmarshaler{new(string)},
630				&ValueRecUnmarshaler{new(string)},
631				ValueRecUnmarshaler{new(string)},
632				&ValueRecUnmarshaler{new(string)},
633			},
634			expected: &struct {
635				ValueRecUnmarshaler    ValueRecUnmarshaler  `csv:"1"`
636				PtrValueRecUnmarshaler *ValueRecUnmarshaler `csv:"2"`
637				Iface                  interface{}          `csv:"3"`
638				Iface2                 interface{}          `csv:"4"`
639			}{
640				ValueRecUnmarshaler{pstring("scan: 1")},
641				&ValueRecUnmarshaler{pstring("scan: 2")},
642				ValueRecUnmarshaler{pstring("scan: 3")},
643				&ValueRecUnmarshaler{pstring("scan: 4")},
644			},
645			regFuncs: []interface{}{
646				func(data []byte, v interface{ Scan([]byte) error }) error {
647					return v.Scan(data)
648				},
649			},
650			expectedRecord: []string{"1", "2", "3", "4"},
651			header:         []string{"1", "2", "3", "4"},
652		},
653		{
654			desc: "decode value receiver textmarshaler",
655			in:   "1,2,3,4\n1,2,3,4",
656			out: &struct {
657				ValueRecTextUnmarshaler    ValueRecTextUnmarshaler  `csv:"1"`
658				PtrValueRecTextUnmarshaler *ValueRecTextUnmarshaler `csv:"2"`
659				Iface                      interface{}              `csv:"3"`
660				Iface2                     interface{}              `csv:"4"`
661			}{
662				ValueRecTextUnmarshaler{new(string)},
663				&ValueRecTextUnmarshaler{new(string)},
664				ValueRecTextUnmarshaler{new(string)},
665				&ValueRecTextUnmarshaler{new(string)},
666			},
667			expected: &struct {
668				ValueRecTextUnmarshaler    ValueRecTextUnmarshaler  `csv:"1"`
669				PtrValueRecTextUnmarshaler *ValueRecTextUnmarshaler `csv:"2"`
670				Iface                      interface{}              `csv:"3"`
671				Iface2                     interface{}              `csv:"4"`
672			}{
673				ValueRecTextUnmarshaler{pstring("1")},
674				&ValueRecTextUnmarshaler{pstring("2")},
675				ValueRecTextUnmarshaler{pstring("3")},
676				&ValueRecTextUnmarshaler{pstring("4")},
677			},
678			expectedRecord: []string{"1", "2", "3", "4"},
679			header:         []string{"1", "2", "3", "4"},
680		},
681
682		{
683			desc: "decode unmarshalers",
684			in:   "csv,pcsv,text,ptext,csv-text,pcsv-text\nfield,field,field,field,field,field",
685			out:  &Unmarshalers{},
686			expected: &Unmarshalers{
687				CSVUnmarshaler:      CSVUnmarshaler{"unmarshalCSV:field"},
688				PCSVUnmarshaler:     &CSVUnmarshaler{"unmarshalCSV:field"},
689				TextUnmarshaler:     TextUnmarshaler{"unmarshalText:field"},
690				PTextUnmarshaler:    &TextUnmarshaler{"unmarshalText:field"},
691				CSVTextUnmarshaler:  CSVTextUnmarshaler{"unmarshalCSV:field"},
692				PCSVTextUnmarshaler: &CSVTextUnmarshaler{"unmarshalCSV:field"},
693			},
694			expectedRecord: []string{"field", "field", "field", "field", "field", "field"},
695			header:         []string{"csv", "pcsv", "text", "ptext", "csv-text", "pcsv-text"},
696		},
697		{
698			desc: "decode embedded tagged unmarshalers",
699			in:   "csv,text,csv-text\nfield,field,field",
700			out:  &EmbeddedUnmarshalers{},
701			expected: &EmbeddedUnmarshalers{
702				CSVUnmarshaler:     CSVUnmarshaler{"unmarshalCSV:field"},
703				TextUnmarshaler:    TextUnmarshaler{"unmarshalText:field"},
704				CSVTextUnmarshaler: CSVTextUnmarshaler{"unmarshalCSV:field"},
705			},
706			expectedRecord: []string{"field", "field", "field"},
707			header:         []string{"csv", "text", "csv-text"},
708		},
709		{
710			desc: "decode pointer embedded tagged unmarshalers",
711			in:   "csv,text,csv-text\nfield,field,field",
712			out:  &EmbeddedPtrUnmarshalers{},
713			expected: &EmbeddedPtrUnmarshalers{
714				CSVUnmarshaler:     &CSVUnmarshaler{"unmarshalCSV:field"},
715				TextUnmarshaler:    &TextUnmarshaler{"unmarshalText:field"},
716				CSVTextUnmarshaler: &CSVTextUnmarshaler{"unmarshalCSV:field"},
717			},
718			expectedRecord: []string{"field", "field", "field"},
719			header:         []string{"csv", "text", "csv-text"},
720		},
721		{
722			desc: "custom header",
723			in:   "string,10",
724			out:  &TypeI{},
725			expected: &TypeI{
726				String: "string",
727				Int:    10,
728			},
729			expectedRecord: []string{"string", "10"},
730			inheader:       []string{"String", "int"},
731			header:         []string{"String", "int"},
732		},
733		{
734			desc: "tag priority over field",
735			in:   "Foo\n1",
736			out:  &TagPriority{},
737			expected: &TagPriority{
738				Foo: 0,
739				Bar: 1,
740			},
741			expectedRecord: []string{"1"},
742			header:         []string{"Foo"},
743		},
744		{
745			desc: "decode into unexported embedded field",
746			in:   "foo,bar\n1,1",
747			out:  &UnexportedEmbedded{},
748			expected: &UnexportedEmbedded{
749				embedded{
750					Foo: 1,
751					bar: 0,
752				},
753			},
754			expectedRecord: []string{"1", "1"},
755			header:         []string{"foo", "bar"},
756			unused:         []int{1},
757		},
758		{
759			desc: "decode into ptr unexported embedded field",
760			in:   "foo,bar\n1,1",
761			out:  &UnexportedEmbeddedPtr{},
762			expected: &UnexportedEmbeddedPtr{
763				&embedded{
764					Foo: 1,
765					bar: 0,
766				},
767			},
768			expectedRecord: []string{"1", "1"},
769			header:         []string{"foo", "bar"},
770			unused:         []int{1},
771			// this test will fail starting go1.10
772			err: ptrUnexportedEmbeddedDecodeErr,
773		},
774		{
775			desc: "embedded field conflict #1",
776			in:   "X,Y\n1,2",
777			out:  &Embedded5{},
778			expected: &Embedded5{
779				Embedded8: Embedded8{
780					Embedded9: Embedded9{Y: 2},
781				},
782			},
783			expectedRecord: []string{"1", "2"},
784			header:         []string{"X", "Y"},
785			unused:         []int{0},
786		},
787		{
788			desc: "embedded field conflict #2",
789			in:   "X,Y\n1,2",
790			out:  &Embedded10{},
791			expected: &Embedded10{
792				Embedded13: Embedded13{
793					Embedded8: Embedded8{
794						Embedded9: Embedded9{Y: 2},
795					},
796				},
797			},
798			expectedRecord: []string{"1", "2"},
799			header:         []string{"X", "Y"},
800			unused:         []int{0},
801		},
802		{
803			desc:           "circular reference",
804			in:             "X,Y\n1,2",
805			out:            &A{},
806			expected:       &A{X: 1, B: B{Y: 2}},
807			expectedRecord: []string{"1", "2"},
808			header:         []string{"X", "Y"},
809		},
810		{
811			desc:           "primitive type alias with Unmarshaler",
812			in:             "enum\nfirst",
813			out:            &EnumType{},
814			expected:       &EnumType{Enum: EnumFirst},
815			expectedRecord: []string{"first"},
816			header:         []string{"enum"},
817		},
818		{
819			desc:           "alias type",
820			in:             "Float\n3.14",
821			out:            &struct{ Float float64 }{},
822			expected:       &struct{ Float float64 }{3.14},
823			expectedRecord: []string{"3.14"},
824			header:         []string{"Float"},
825		},
826		{
827			desc:           "empty base64 string",
828			in:             "Binary,foo\n,1\n",
829			out:            &struct{ Binary []byte }{},
830			expected:       &struct{ Binary []byte }{[]byte{}},
831			expectedRecord: []string{"", "1"},
832			header:         []string{"Binary", "foo"},
833			unused:         []int{1},
834		},
835		{
836			desc: "inline fields",
837			in: "int,Bool,Uint8,float,prefix-STR,prefix-int,prefix-Bool,prefix-Uint8,prefix-float,top-string,STR\n" +
838				"1,true,1,1,j2,2,true,2,2,top-level-str,STR",
839			out: &Inline{},
840			expected: &Inline{
841				J1: TypeJ{
842					Int:        "1",
843					Float:      "1",
844					Embedded16: Embedded16{Bool: true, Uint8: 1},
845				},
846				J2: TypeJ{
847					String:     "j2",
848					Int:        "2",
849					Float:      "2",
850					Embedded16: Embedded16{Bool: true, Uint8: 2},
851				},
852				String:  "top-level-str",
853				String2: "STR",
854			},
855			expectedRecord: []string{"1", "true", "1", "1", "j2", "2", "true", "2", "2", "top-level-str", "STR"},
856			header:         []string{"int", "Bool", "Uint8", "float", "prefix-STR", "prefix-int", "prefix-Bool", "prefix-Uint8", "prefix-float", "top-string", "STR"},
857		},
858		{
859			desc: "inline chain",
860			in:   "AS,AAA,AA,S,A\n1,11,34,2,22",
861			out:  &Inline5{},
862			expected: &Inline5{
863				A: Inline2{
864					S: "1",
865					A: Inline3{
866						Inline4: Inline4{A: "11"},
867					},
868				},
869				B: Inline2{
870					S: "2",
871					B: Inline3{
872						Inline4: Inline4{A: "22"},
873					},
874				},
875			},
876			unused:         []int{2},
877			expectedRecord: []string{"1", "11", "34", "2", "22"},
878			header:         []string{"AS", "AAA", "AA", "S", "A"},
879		},
880		{
881			desc: "cyclic inline - no prefix",
882			in:   "X\n1",
883			out:  &Inline6{},
884			expected: &Inline6{
885				A: Inline7{
886					A: nil,
887					X: 1,
888				},
889			},
890			expectedRecord: []string{"1"},
891			header:         []string{"X"},
892		},
893		{
894			desc: "inline visibility rules",
895			in:   "AA\n1",
896			out:  &Inline8{},
897			expected: &Inline8{
898				AA: 1,
899			},
900			expectedRecord: []string{"1"},
901			header:         []string{"AA"},
902		},
903		{
904			desc: "initialized interface",
905			in:   "Int,Float,String,Bool,Unmarshaler,NilPtr\n10,3.14,string,true,lol,nil",
906			out: &struct{ Int, Float, String, Bool, Unmarshaler, NilPtr interface{} }{
907				Int:         int(0),
908				Float:       float64(0),
909				String:      "",
910				Bool:        false,
911				Unmarshaler: CSVUnmarshaler{},
912				NilPtr:      (*int)(nil),
913			},
914			expected: &struct{ Int, Float, String, Bool, Unmarshaler, NilPtr interface{} }{
915				Int:         "10",
916				Float:       "3.14",
917				String:      "string",
918				Bool:        "true",
919				Unmarshaler: "lol",
920				NilPtr:      "nil",
921			},
922			expectedRecord: []string{"10", "3.14", "string", "true", "lol", "nil"},
923			header:         []string{"Int", "Float", "String", "Bool", "Unmarshaler", "NilPtr"},
924		},
925		{
926			desc: "initialized ptr interface",
927			in:   "Int,Float,String,Bool,Unmarshaler,DoublePtr\n10,3.14,string,true,lol,100",
928			out: &struct{ Int, Float, String, Bool, Unmarshaler, DoublePtr interface{} }{
929				Int:         pint(0),
930				Float:       pfloat64(0),
931				String:      pstring(""),
932				Bool:        pbool(false),
933				Unmarshaler: &CSVUnmarshaler{},
934				DoublePtr:   ppint(0),
935			},
936			expected: &struct{ Int, Float, String, Bool, Unmarshaler, DoublePtr interface{} }{
937				Int:    pint(10),
938				Float:  pfloat64(3.14),
939				String: pstring("string"),
940				Bool:   pbool(true),
941				Unmarshaler: &CSVUnmarshaler{
942					String: "unmarshalCSV:lol",
943				},
944				DoublePtr: ppint(100),
945			},
946			expectedRecord: []string{"10", "3.14", "string", "true", "lol", "100"},
947			header:         []string{"Int", "Float", "String", "Bool", "Unmarshaler", "DoublePtr"},
948		},
949		{
950			desc: "initialized ptr interface fields",
951			in:   "Int,Float,String,Bool,Unmarshaler\n10,3.14,string,true,lol",
952			out: &struct{ Int, Float, String, Bool, Unmarshaler *interface{} }{
953				Int:         pinterface(int(0)),
954				Float:       pinterface(float64(0)),
955				String:      pinterface(""),
956				Bool:        pinterface(false),
957				Unmarshaler: pinterface(CSVUnmarshaler{}),
958			},
959			expected: &struct{ Int, Float, String, Bool, Unmarshaler *interface{} }{
960				Int:         pinterface("10"),
961				Float:       pinterface("3.14"),
962				String:      pinterface("string"),
963				Bool:        pinterface("true"),
964				Unmarshaler: pinterface("lol"),
965			},
966			expectedRecord: []string{"10", "3.14", "string", "true", "lol"},
967			header:         []string{"Int", "Float", "String", "Bool", "Unmarshaler"},
968		},
969		{
970			desc: "initialized ptr interface fields to ptr values",
971			in:   "Int,Float,String,Bool,Unmarshaler,DoublePtr\n10,3.14,string,true,lol,30",
972			out: &struct{ Int, Float, String, Bool, Unmarshaler, DoublePtr *interface{} }{
973				Int:         pinterface(pint(0)),
974				Float:       pinterface(pfloat64(0)),
975				String:      pinterface(pstring("")),
976				Bool:        pinterface(pbool(false)),
977				Unmarshaler: pinterface(&CSVUnmarshaler{}),
978				DoublePtr:   pinterface(ppint(0)),
979			},
980			expected: &struct{ Int, Float, String, Bool, Unmarshaler, DoublePtr *interface{} }{
981				Int:    pinterface(pint(10)),
982				Float:  pinterface(pfloat64(3.14)),
983				String: pinterface(pstring("string")),
984				Bool:   pinterface(pbool(true)),
985				Unmarshaler: pinterface(&CSVUnmarshaler{
986					String: "unmarshalCSV:lol",
987				}),
988				DoublePtr: pinterface(ppint(30)),
989			},
990			expectedRecord: []string{"10", "3.14", "string", "true", "lol", "30"},
991			header:         []string{"Int", "Float", "String", "Bool", "Unmarshaler", "DoublePtr"},
992		},
993		{
994			desc: "nil slice of structs",
995			in:   "String,int\nfirst,1\nsecond,2",
996			out:  &TypeISlice,
997			expected: &[]TypeI{
998				{String: "first", Int: 1},
999				{String: "second", Int: 2},
1000			},
1001			expectedRecord: nil,
1002			header:         []string{"String", "int"},
1003		},
1004		{
1005			desc: "slice of structs",
1006			in:   "String,int\nfirst,1\nsecond,2",
1007			out:  &[]TypeI{},
1008			expected: &[]TypeI{
1009				{String: "first", Int: 1},
1010				{String: "second", Int: 2},
1011			},
1012			expectedRecord: nil,
1013			header:         []string{"String", "int"},
1014		},
1015		{
1016			desc: "slice of structs - pre-allocated",
1017			in:   "String,int\nfirst,1\nsecond,2",
1018			out:  &[]TypeI{0: TypeI{Int: 200}, 1024: TypeI{Int: 100}},
1019			expected: &[]TypeI{
1020				{String: "first", Int: 1},
1021				{String: "second", Int: 2},
1022			},
1023			expectedRecord: nil,
1024			header:         []string{"String", "int"},
1025		},
1026		{
1027			desc: "slice of pointer structs",
1028			in:   "String,int\nfirst,1\nsecond,2",
1029			out:  &[]*TypeI{},
1030			expected: &[]*TypeI{
1031				{String: "first", Int: 1},
1032				{String: "second", Int: 2},
1033			},
1034			expectedRecord: nil,
1035			header:         []string{"String", "int"},
1036		},
1037		{
1038			desc: "slice of double pointer structs",
1039			in:   "String,int\nfirst,1\nsecond,2",
1040			out:  &[]**TypeI{},
1041			expected: &[]**TypeI{
1042				ppTypeI(TypeI{String: "first", Int: 1}),
1043				ppTypeI(TypeI{String: "second", Int: 2}),
1044			},
1045			expectedRecord: nil,
1046			header:         []string{"String", "int"},
1047		},
1048		{
1049			desc: "invalid slice of interfaces",
1050			in:   "String,int\nfirst,1",
1051			out:  &[]interface{}{},
1052			err: &InvalidDecodeError{
1053				Type: reflect.TypeOf(&[]interface{}{}),
1054			},
1055		},
1056		{
1057			desc: "invalid slice of ints",
1058			in:   "String,int\nfirst,1",
1059			out:  &[]int{},
1060			err: &InvalidDecodeError{
1061				Type: reflect.TypeOf(&[]int{}),
1062			},
1063		},
1064		{
1065			desc: "invalid non pointer slice of ints",
1066			in:   "String,int\nfirst,1",
1067			out:  []int{},
1068			err: &InvalidDecodeError{
1069				Type: reflect.TypeOf([]int{}),
1070			},
1071		},
1072		{
1073			desc: "array of structs",
1074			in:   "String,int\nfirst,1\nsecond,2",
1075			out:  &[2]TypeI{},
1076			expected: &[2]TypeI{
1077				{String: "first", Int: 1},
1078				{String: "second", Int: 2},
1079			},
1080			expectedRecord: []string{"second", "2"},
1081			header:         []string{"String", "int"},
1082		},
1083		{
1084			desc: "array of pointer structs",
1085			in:   "String,int\nfirst,1\nsecond,2",
1086			out:  &[2]*TypeI{},
1087			expected: &[2]*TypeI{
1088				{String: "first", Int: 1},
1089				{String: "second", Int: 2},
1090			},
1091			expectedRecord: []string{"second", "2"},
1092			header:         []string{"String", "int"},
1093		},
1094		{
1095			desc: "array of double pointer structs",
1096			in:   "String,int\nfirst,1\nsecond,2",
1097			out:  &[2]**TypeI{},
1098			expected: &[2]**TypeI{
1099				ppTypeI(TypeI{String: "first", Int: 1}),
1100				ppTypeI(TypeI{String: "second", Int: 2}),
1101			},
1102			expectedRecord: []string{"second", "2"},
1103			header:         []string{"String", "int"},
1104		},
1105		{
1106			desc: "array of structs - bigger than the data set",
1107			in:   "String,int\nfirst,1\nsecond,2",
1108			out: &[4]TypeI{
1109				3: {String: "I should be zeroed out", Int: 1024},
1110			},
1111			expected: &[4]TypeI{
1112				0: {String: "first", Int: 1},
1113				1: {String: "second", Int: 2},
1114			},
1115			expectedRecord: nil,
1116			header:         []string{"String", "int"},
1117		},
1118		{
1119			desc: "array of structs - smaller than the data set",
1120			in:   "String,int\nfirst,1\nsecond,2",
1121			out:  &[1]TypeI{},
1122			expected: &[1]TypeI{
1123				0: {String: "first", Int: 1},
1124			},
1125			expectedRecord: []string{"first", "1"},
1126			header:         []string{"String", "int"},
1127		},
1128		{
1129			desc: "invalid array of interfaces",
1130			in:   "String,int\nfirst,1",
1131			out:  &[1]interface{}{},
1132			err: &InvalidDecodeError{
1133				Type: reflect.TypeOf(&[1]interface{}{}),
1134			},
1135		},
1136		{
1137			desc: "invalid array of ints",
1138			in:   "String,int\nfirst,1",
1139			out:  &[1]int{},
1140			err: &InvalidDecodeError{
1141				Type: reflect.TypeOf(&[1]int{}),
1142			},
1143		},
1144		{
1145			desc: "invalid non pointer array of ints",
1146			in:   "String,int\nfirst,1",
1147			out:  [1]int{},
1148			err: &InvalidDecodeError{
1149				Type: reflect.TypeOf([1]int{}),
1150			},
1151		},
1152		{
1153			desc: "unsupported type",
1154			in:   "string,int\ns,1",
1155			out:  &TypeWithInvalidField{},
1156			err: &UnsupportedTypeError{
1157				Type: reflect.TypeOf(TypeI{}),
1158			},
1159		},
1160		{
1161			desc: "unsupported double ptr type",
1162			in:   "A\n1",
1163			out: &struct {
1164				A **struct{}
1165			}{},
1166			err: &UnsupportedTypeError{
1167				Type: reflect.TypeOf(struct{}{}),
1168			},
1169		},
1170		{
1171			desc: "invalid int",
1172			in:   "Int,Foo\n,",
1173			out:  &struct{ Int int }{},
1174			err:  &UnmarshalTypeError{Value: "", Type: reflect.TypeOf(int(0))},
1175		},
1176		{
1177			desc: "int overflow",
1178			in:   "Int\n1024",
1179			out:  &struct{ Int int8 }{},
1180			err:  &UnmarshalTypeError{Value: "1024", Type: reflect.TypeOf(int8(0))},
1181		},
1182		{
1183			desc: "invalid int pointer",
1184			in:   "Int,Foo\nbar,",
1185			out:  &struct{ Int *int }{},
1186			err:  &UnmarshalTypeError{Value: "bar", Type: reflect.TypeOf(int(0))},
1187		},
1188		{
1189			desc: "invalid type pointer",
1190			in:   "Int,Foo\n,",
1191			out:  &struct{ Int *struct{} }{},
1192			err:  &UnsupportedTypeError{Type: reflect.TypeOf(struct{}{})},
1193		},
1194		{
1195			desc: "invalid uint",
1196			in:   "Uint,Foo\n,",
1197			out:  &struct{ Uint uint }{},
1198			err:  &UnmarshalTypeError{Value: "", Type: reflect.TypeOf(uint(0))},
1199		},
1200		{
1201			desc: "uint overflow",
1202			in:   "Uint\n1024",
1203			out:  &struct{ Uint uint8 }{},
1204			err:  &UnmarshalTypeError{Value: "1024", Type: reflect.TypeOf(uint8(0))},
1205		},
1206		{
1207			desc: "invalid uint pointer",
1208			in:   "Uint\na",
1209			out:  &struct{ Uint *uint }{},
1210			err:  &UnmarshalTypeError{Value: "a", Type: reflect.TypeOf(uint(0))},
1211		},
1212		{
1213			desc: "invalid float",
1214			in:   "Float,Foo\n,",
1215			out:  &struct{ Float float64 }{},
1216			err:  &UnmarshalTypeError{Value: "", Type: reflect.TypeOf(float64(0))},
1217		},
1218		{
1219			desc: "invalid float pointer",
1220			in:   "Float\na",
1221			out:  &struct{ Float *float64 }{},
1222			err:  &UnmarshalTypeError{Value: "a", Type: reflect.TypeOf(float64(0))},
1223		},
1224		{
1225			desc: "invalid bool",
1226			in:   "Bool,Foo\n,",
1227			out:  &struct{ Bool bool }{},
1228			err:  &UnmarshalTypeError{Value: "", Type: reflect.TypeOf(bool(false))},
1229		},
1230		{
1231			desc: "invalid interface",
1232			in:   "Interface,Foo\n,",
1233			out:  &struct{ Interface Unmarshaler }{},
1234			err:  &UnmarshalTypeError{Value: "", Type: csvUnmarshaler},
1235		},
1236		{
1237			desc: "invalid interface pointer",
1238			in:   "Interface,Foo\nbar,",
1239			out:  &struct{ Interface *Unmarshaler }{},
1240			err:  &UnmarshalTypeError{Value: "bar", Type: csvUnmarshaler},
1241		},
1242		{
1243			desc: "invalid field in embedded type",
1244			in:   "String,int\n1,1",
1245			out:  &struct{ InvalidType }{},
1246			err:  &UnsupportedTypeError{Type: reflect.TypeOf(struct{}{})},
1247		},
1248		{
1249			desc: "not a struct in decode",
1250			in:   "string,int\n1,1",
1251			out:  &Int,
1252			err:  &InvalidDecodeError{Type: reflect.TypeOf(&Int)},
1253		},
1254		{
1255			desc: "not a struct in decode - non ptr",
1256			in:   "string,int\n1,1",
1257			out:  Int,
1258			err:  &InvalidDecodeError{Type: reflect.TypeOf(Int)},
1259		},
1260		{
1261			desc: "invalid base64 string",
1262			in:   "Binary\n1",
1263			out:  &struct{ Binary []byte }{},
1264			err:  base64.CorruptInputError(0),
1265		},
1266		{
1267			desc: "invalid int under interface value",
1268			in:   "Int,Foo\n,",
1269			out:  &struct{ Int interface{} }{Int: pint(0)},
1270			err:  &UnmarshalTypeError{Value: "", Type: reflect.TypeOf(int(0))},
1271		},
1272		{
1273			desc: "unsupported type under interface value",
1274			in:   "Invalid\n1",
1275			out:  &struct{ Invalid interface{} }{Invalid: &InvalidType{}},
1276			err:  &UnsupportedTypeError{Type: reflect.TypeOf(InvalidType{})},
1277		},
1278		{
1279			desc: "no panic on embedded pointer fields with blank value",
1280			in:   "X,Y\n,",
1281			out:  &Embedded17{},
1282			expected: &Embedded17{
1283				Embedded18: &Embedded18{},
1284			},
1285			expectedRecord: []string{"", ""},
1286			header:         []string{"X", "Y"},
1287		},
1288		{
1289			desc: "set blank values to nil on pointers",
1290			in:   "X,Y\n1,",
1291			out: &Embedded17{
1292				Embedded18: &Embedded18{
1293					X: pfloat64(10),
1294					Y: pfloat64(20),
1295				},
1296			},
1297			expected: &Embedded17{
1298				Embedded18: &Embedded18{
1299					X: pfloat64(1),
1300					Y: nil,
1301				},
1302			},
1303			expectedRecord: []string{"1", ""},
1304			header:         []string{"X", "Y"},
1305		},
1306		{
1307			desc: "no panic on embedded pointer fields with blank value 2",
1308			in:   "X,Y\n1,",
1309			out:  &Embedded17{},
1310			expected: &Embedded17{
1311				Embedded18: &Embedded18{X: pfloat64(1)},
1312			},
1313			expectedRecord: []string{"1", ""},
1314			header:         []string{"X", "Y"},
1315		},
1316		{
1317			desc: "fails on blank non float string with ptr embedded",
1318			in:   "string,float\n,",
1319			out:  &TypeC{},
1320			err:  &UnmarshalTypeError{Type: reflect.TypeOf(float64(0)), Value: ""},
1321		},
1322		{
1323			desc: "blank values on embedded pointers",
1324			in:   "String,Int\n,",
1325			out:  &TypeK{},
1326			expected: &TypeK{
1327				&TypeL{String: "", Int: 0},
1328			},
1329			expectedRecord: []string{"", ""},
1330			header:         []string{"String", "Int"},
1331		},
1332		{
1333			desc: "blank values on pointers decode to nil",
1334			in: "int,pint,int8,pint8,int16,pint16,int32,pint32,int64,pint64,uint," +
1335				"puint,uint8,puint8,uint16,puint16,uint32,puint32,uint64,puint64,float32," +
1336				"pfloat32,float64,pfloat64,string,pstring,bool,pbool,interface,pinterface,binary,pbinary\n" +
1337				"1,,3,,5,,7,,9,,11,,13,,15,,17,,19,,21,,23,,25,,true,,true,," +
1338				EncodedBinary + "," + "",
1339			out: &TypeF{
1340				Pint: pint(10),
1341			},
1342			expected: &TypeF{
1343				Int:      1,
1344				Pint:     nil,
1345				Int8:     3,
1346				Pint8:    nil,
1347				Int16:    5,
1348				Pint16:   nil,
1349				Int32:    7,
1350				Pint32:   nil,
1351				Int64:    9,
1352				Pint64:   nil,
1353				UInt:     11,
1354				Puint:    nil,
1355				Uint8:    13,
1356				Puint8:   nil,
1357				Uint16:   15,
1358				Puint16:  nil,
1359				Uint32:   17,
1360				Puint32:  nil,
1361				Uint64:   19,
1362				Puint64:  nil,
1363				Float32:  21,
1364				Pfloat32: nil,
1365				Float64:  23,
1366				Pfloat64: nil,
1367				String:   "25",
1368				PString:  nil,
1369				Bool:     true,
1370				Pbool:    nil,
1371				V:        "true",
1372				Pv:       nil,
1373				Binary:   Binary,
1374				PBinary:  nil,
1375			},
1376			expectedRecord: []string{"1", "", "3", "", "5", "", "7", "", "9", "", "11", "",
1377				"13", "", "15", "", "17", "", "19", "", "21", "", "23", "", "25", "",
1378				"true", "", "true", "", EncodedBinary, ""},
1379			header: []string{"int",
1380				"pint",
1381				"int8",
1382				"pint8",
1383				"int16",
1384				"pint16",
1385				"int32",
1386				"pint32",
1387				"int64",
1388				"pint64",
1389				"uint",
1390				"puint",
1391				"uint8",
1392				"puint8",
1393				"uint16",
1394				"puint16",
1395				"uint32",
1396				"puint32",
1397				"uint64",
1398				"puint64",
1399				"float32",
1400				"pfloat32",
1401				"float64",
1402				"pfloat64",
1403				"string",
1404				"pstring",
1405				"bool",
1406				"pbool",
1407				"interface",
1408				"pinterface",
1409				"binary",
1410				"pbinary",
1411			},
1412		},
1413		{
1414			desc: "registered func",
1415			in:   "Int,Pint,Iface,Piface\na,b,c,d",
1416			out: &struct {
1417				Int    int
1418				Pint   *int
1419				Iface  interface{}
1420				Piface *interface{}
1421			}{Iface: pint(10), Piface: pinterface(pint(10))},
1422			expected: &struct {
1423				Int    int
1424				Pint   *int
1425				Iface  interface{}
1426				Piface *interface{}
1427			}{
1428				Int:    10,
1429				Pint:   pint(11),
1430				Iface:  pint(12),
1431				Piface: pinterface(pint(13)),
1432			},
1433			regFuncs: []interface{}{
1434				func(data []byte, n *int) error {
1435					x, err := strconv.ParseInt(string(data), 16, 64)
1436					if err != nil {
1437						return err
1438					}
1439					*n = int(x)
1440					return nil
1441				},
1442			},
1443			expectedRecord: []string{"a", "b", "c", "d"},
1444			header:         []string{"Int", "Pint", "Iface", "Piface"},
1445		},
1446		{
1447			desc: "registered func - initialized interface ptr",
1448			in:   "Iface,Piface\na,b",
1449			out: &struct {
1450				Iface  interface{}
1451				Piface *interface{}
1452			}{Iface: 10, Piface: pinterface(10)},
1453			expected: &struct {
1454				Iface  interface{}
1455				Piface *interface{}
1456			}{
1457				Iface:  "a",
1458				Piface: pinterface("b"),
1459			},
1460			regFuncs: []interface{}{
1461				func(data []byte, n *int) error {
1462					x, err := strconv.ParseInt(string(data), 16, 64)
1463					if err != nil {
1464						return err
1465					}
1466					*n = int(x)
1467					return nil
1468				},
1469			},
1470			expectedRecord: []string{"a", "b"},
1471			header:         []string{"Iface", "Piface"},
1472		},
1473		{
1474			desc: "registered func - interfaces",
1475			in:   "Int,Pint,Iface,Piface,Scanner,PScanner\n10,20,30,40,50,60",
1476			out: &struct {
1477				Int      IntStruct
1478				Pint     *IntStruct
1479				Iface    interface{}
1480				Piface   *interface{}
1481				Scanner  fmt.Scanner
1482				PScanner *fmt.Scanner
1483			}{
1484				Iface:    &IntStruct{},
1485				Piface:   pinterface(&IntStruct{}),
1486				Scanner:  &IntStruct{},
1487				PScanner: &[]fmt.Scanner{&IntStruct{}}[0],
1488			},
1489			expected: &struct {
1490				Int      IntStruct
1491				Pint     *IntStruct
1492				Iface    interface{}
1493				Piface   *interface{}
1494				Scanner  fmt.Scanner
1495				PScanner *fmt.Scanner
1496			}{
1497				Int:      IntStruct{Value: 10},
1498				Pint:     &IntStruct{Value: 20},
1499				Iface:    &IntStruct{Value: 30},
1500				Piface:   pinterface(&IntStruct{Value: 40}),
1501				Scanner:  &IntStruct{Value: 50},
1502				PScanner: &[]fmt.Scanner{&IntStruct{Value: 60}}[0],
1503			},
1504			regFuncs: []interface{}{
1505				func(data []byte, scanner fmt.Scanner) error {
1506					_, err := fmt.Sscan(string(data), scanner)
1507					return err
1508				},
1509			},
1510			expectedRecord: []string{"10", "20", "30", "40", "50", "60"},
1511			header:         []string{"Int", "Pint", "Iface", "Piface", "Scanner", "PScanner"},
1512		},
1513		{
1514			desc: "registered func - invalid interface",
1515			in:   "Foo\n1",
1516			regFuncs: []interface{}{
1517				func(data []byte, scanner fmt.Scanner) error {
1518					_, err := fmt.Sscan(string(data), scanner)
1519					return err
1520				},
1521			},
1522			out: &struct{ Foo fmt.Scanner }{},
1523			err: &UnmarshalTypeError{Value: "1", Type: reflect.TypeOf((*fmt.Scanner)(nil)).Elem()},
1524		},
1525		{
1526			desc: "registered func - invalid *interface",
1527			in:   "Foo\n1",
1528			regFuncs: []interface{}{
1529				func(data []byte, scanner fmt.Scanner) error {
1530					_, err := fmt.Sscan(string(data), scanner)
1531					return err
1532				},
1533			},
1534			out: &struct{ Foo *fmt.Scanner }{},
1535			err: &UnmarshalTypeError{Value: "1", Type: reflect.TypeOf((*fmt.Scanner)(nil)).Elem()},
1536		},
1537		{
1538			desc: "registered func - non ptr interface",
1539			in:   "Foo\n1",
1540			regFuncs: []interface{}{
1541				func(data []byte, scanner fmt.Scanner) error {
1542					_, err := fmt.Sscan(string(data), scanner)
1543					return err
1544				},
1545			},
1546			out:            &struct{ Foo interface{} }{Foo: (fmt.Scanner)(nil)},
1547			expected:       &struct{ Foo interface{} }{Foo: "1"},
1548			expectedRecord: []string{"1"},
1549			header:         []string{"Foo"},
1550		},
1551		{
1552			desc: "registered func - ptr interface",
1553			in:   "Foo\n1",
1554			regFuncs: []interface{}{
1555				func(data []byte, scanner fmt.Scanner) error {
1556					_, err := fmt.Sscan(string(data), scanner)
1557					return err
1558				},
1559			},
1560			out:            &struct{ Foo interface{} }{Foo: (*fmt.Scanner)(nil)},
1561			expected:       &struct{ Foo interface{} }{Foo: "1"},
1562			expectedRecord: []string{"1"},
1563			header:         []string{"Foo"},
1564		},
1565	}
1566
1567	for _, f := range fixtures {
1568		t.Run(f.desc, func(t *testing.T) {
1569			r, err := NewDecoder(newCSVReader(strings.NewReader(f.in)), f.inheader...)
1570			if err != nil {
1571				t.Fatal(err)
1572			}
1573
1574			for _, fn := range f.regFuncs {
1575				r.Register(fn)
1576			}
1577
1578			err = r.Decode(&f.out)
1579			if f.err != nil {
1580				if !reflect.DeepEqual(f.err, err) {
1581					t.Errorf("want err=%v; got %v", f.err, err)
1582				}
1583				return
1584			}
1585
1586			if err != nil {
1587				t.Errorf("want err=nil; got %v", err)
1588			}
1589
1590			if !reflect.DeepEqual(r.Record(), f.expectedRecord) {
1591				t.Errorf("want rec=%q; got %q", f.expectedRecord, r.Record())
1592			}
1593
1594			if !reflect.DeepEqual(f.out, f.expected) {
1595				t.Errorf("want %#v; got %#v", f.expected, f.out)
1596			}
1597
1598			if !reflect.DeepEqual(r.Unused(), f.unused) {
1599				t.Errorf("want unused=%v; got %v", f.unused, r.Unused())
1600			}
1601
1602			if !reflect.DeepEqual(r.Header(), f.header) {
1603				t.Errorf("want header=%v; got %v", f.header, r.Header())
1604			}
1605		})
1606	}
1607
1608	t.Run("decode with custom tag", func(t *testing.T) {
1609		type Type struct {
1610			String string `customtag:"string"`
1611			Int    int    `customtag:"int"`
1612		}
1613
1614		dec, err := NewDecoder(NewReader([]string{"string", "10"}), "string", "int")
1615		if err != nil {
1616			t.Fatal(err)
1617		}
1618		dec.Tag = "customtag"
1619
1620		var tt Type
1621		if err := dec.Decode(&tt); err != nil {
1622			t.Errorf("want err=nil; got %v", err)
1623		}
1624
1625		expected := Type{"string", 10}
1626		if !reflect.DeepEqual(tt, expected) {
1627			t.Errorf("want tt=%v; got %v", expected, tt)
1628		}
1629	})
1630
1631	t.Run("invalid unmarshal tests", func(t *testing.T) {
1632		var fixtures = []struct {
1633			v        interface{}
1634			expected string
1635		}{
1636			{nil, "csvutil: Decode(nil)"},
1637			{nilIface, "csvutil: Decode(nil)"},
1638			{struct{}{}, "csvutil: Decode(non-pointer struct {})"},
1639			{int(1), "csvutil: Decode(non-pointer int)"},
1640			{[]int{}, "csvutil: Decode(non-pointer []int)"},
1641			{(*int)(nil), "csvutil: Decode(invalid type *int)"},
1642			{(*[]int)(nil), "csvutil: Decode(invalid type *[]int)"},
1643			{(*[]*int)(nil), "csvutil: Decode(invalid type *[]*int)"},
1644			{(*[1]*int)(nil), "csvutil: Decode(invalid type *[1]*int)"},
1645			{&nilIface, "csvutil: Decode(invalid type *interface {})"},
1646			{(*TypeA)(nil), "csvutil: Decode(nil *csvutil.TypeA)"},
1647		}
1648
1649		for _, f := range fixtures {
1650			r, err := NewDecoder(newCSVReader(strings.NewReader("string\ns")))
1651			if err != nil {
1652				t.Fatal(err)
1653			}
1654			err = r.Decode(f.v)
1655			if err == nil {
1656				t.Errorf("Decode expecting error, got nil")
1657				continue
1658			}
1659			if got := err.Error(); got != f.expected {
1660				t.Errorf("want Decode=%q; got %q", f.expected, got)
1661			}
1662		}
1663	})
1664
1665	t.Run("header and field length mismatch", func(t *testing.T) {
1666		type Foo struct {
1667			Col1 string `csv:"col1"`
1668			Col2 string `csv:"col2"`
1669		}
1670		data := []byte("1,1,1")
1671		r, err := NewDecoder(newCSVReader(bytes.NewReader(data)), "col1", "col2")
1672		if err != nil {
1673			t.Fatal(err)
1674		}
1675
1676		var foo Foo
1677		if err := r.Decode(&foo); err != ErrFieldCount {
1678			t.Errorf("want err=%v; got %v", ErrFieldCount, err)
1679		}
1680	})
1681
1682	t.Run("decode different types", func(t *testing.T) {
1683		data := []byte(`
1684String,Int,Float,Bool
1685s,1,3.14,true
1686s,1,3.14,true
1687s,1,3.14,true
1688`)
1689
1690		type A struct {
1691			String string
1692			Foo    string
1693		}
1694
1695		type B struct {
1696			Int int
1697			Foo int
1698		}
1699
1700		type C struct {
1701			Bool   bool
1702			Float  float64
1703			Int    int
1704			String string
1705			Foo    int
1706		}
1707
1708		dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1709		if err != nil {
1710			t.Errorf("want err=nil; got %v", err)
1711		}
1712
1713		fixtures := []struct {
1714			out      interface{}
1715			expected interface{}
1716			unused   []int
1717		}{
1718			{
1719				out:      &A{},
1720				expected: &A{String: "s"},
1721				unused:   []int{1, 2, 3},
1722			},
1723			{
1724				out:      &B{},
1725				expected: &B{Int: 1},
1726				unused:   []int{0, 2, 3},
1727			},
1728			{
1729				out: &C{},
1730				expected: &C{
1731					Bool:   true,
1732					Float:  3.14,
1733					Int:    1,
1734					String: "s",
1735				},
1736			},
1737		}
1738
1739		for _, f := range fixtures {
1740			if err := dec.Decode(f.out); err != nil {
1741				t.Errorf("want err=nil; got %v", err)
1742			}
1743			if !reflect.DeepEqual(f.out, f.expected) {
1744				t.Errorf("want %v; got %v", f.expected, f.out)
1745			}
1746			if !reflect.DeepEqual(dec.Unused(), f.unused) {
1747				t.Errorf("want %v; got %v", f.unused, dec.Unused())
1748			}
1749		}
1750	})
1751
1752	t.Run("decode NaN", func(t *testing.T) {
1753		data := []byte("F1,F2,F3,F4,F5\nNaN,nan,NAN,nAn,NaN")
1754		dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1755		if err != nil {
1756			t.Fatalf("want err=nil; got %v", err)
1757		}
1758
1759		v := struct {
1760			F1, F2, F3, F4 float64
1761			F5             Float // aliased type
1762		}{}
1763		if err := dec.Decode(&v); err != nil {
1764			t.Fatalf("want err=nil; got %v", err)
1765		}
1766
1767		for _, f := range []float64{v.F1, v.F2, v.F3, v.F4, float64(v.F5)} {
1768			if !math.IsNaN(f) {
1769				t.Errorf("want f=NaN; got %v", f)
1770			}
1771		}
1772	})
1773
1774	t.Run("map", func(t *testing.T) {
1775		t.Run("receives non-pointer and non-interface zero values", func(t *testing.T) {
1776			data := []byte("int,pint,int8,pint8,int16,pint16,int32,pint32,int64,pint64,uint," +
1777				"puint,uint8,puint8,uint16,puint16,uint32,puint32,uint64,puint64,float32," +
1778				"pfloat32,float64,pfloat64,string,pstring,bool,pbool,interface,pinterface,binary,pbinary\n" +
1779				"1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,true,true,true,1," +
1780				EncodedBinary + "," + EncodedBinaryLarge)
1781
1782			dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1783			if err != nil {
1784				t.Fatalf("want err=nil; got %v", err)
1785			}
1786
1787			var out TypeF
1788			var counter int
1789			m := func(field, col string, v interface{}) string {
1790				switch v.(type) {
1791				case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64,
1792					float32, float64, string, bool, []byte:
1793					counter++ // interface values are passed as strings.
1794				}
1795				return field
1796			}
1797			dec.Map = m
1798
1799			if err := dec.Decode(&out); err != nil {
1800				t.Errorf("want err=nil; got %v", err)
1801			}
1802			if numField := reflect.TypeOf(out).NumField(); counter != numField {
1803				t.Errorf("expected counter=%d; got %d", numField, counter)
1804			}
1805		})
1806
1807		t.Run("replaced value", func(t *testing.T) {
1808			m := func(field, col string, v interface{}) string {
1809				if _, ok := v.(float64); ok && field == "n/a" {
1810					return "NaN"
1811				}
1812				return field
1813			}
1814
1815			data := []byte("F1,F2,F3\nn/a,n/a,n/a")
1816			dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1817			if err != nil {
1818				t.Fatalf("want err=nil; got %v", err)
1819			}
1820			dec.Map = m
1821
1822			var out struct {
1823				F1 float64
1824				F2 *float64
1825				F3 **float64
1826			}
1827			if err := dec.Decode(&out); err != nil {
1828				t.Errorf("want err=nil; got %v", err)
1829			}
1830			if !math.IsNaN(out.F1) {
1831				t.Errorf("want F1 to be NaN but is %f", out.F1)
1832			}
1833			if out.F2 == nil {
1834				t.Error("want F2 to not be nil")
1835			}
1836			if !math.IsNaN(*out.F2) {
1837				t.Errorf("want F2 to be NaN but is %f", *out.F2)
1838			}
1839			if out.F3 == nil {
1840				t.Error("want F3 to not be nil")
1841			}
1842			if *out.F3 == nil {
1843				t.Error("want *F3 to not be nil")
1844			}
1845			if !math.IsNaN(**out.F3) {
1846				t.Errorf("want F3 to be NaN but is %f", **out.F3)
1847			}
1848		})
1849
1850		t.Run("unmarshaler types", func(t *testing.T) {
1851			m := func(field, col string, v interface{}) string {
1852				if _, ok := v.(CSVUnmarshaler); ok && field == "" {
1853					return "csv_unmarshaler"
1854				}
1855				if _, ok := v.(TextUnmarshaler); ok && field == "" {
1856					return "text_unmarshaler"
1857				}
1858				return field
1859			}
1860
1861			data := []byte("csv,pcsv,text,ptext\n,,,")
1862			dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1863			if err != nil {
1864				t.Fatalf("want err=nil; got %v", err)
1865			}
1866			dec.Map = m
1867
1868			var out Unmarshalers
1869			if err := dec.Decode(&out); err != nil {
1870				t.Errorf("want err=nil; got %v", err)
1871			}
1872
1873			expected := Unmarshalers{
1874				CSVUnmarshaler:   CSVUnmarshaler{String: "unmarshalCSV:csv_unmarshaler"},
1875				PCSVUnmarshaler:  nil,
1876				TextUnmarshaler:  TextUnmarshaler{String: "unmarshalText:text_unmarshaler"},
1877				PTextUnmarshaler: nil,
1878			}
1879
1880			if !reflect.DeepEqual(out, expected) {
1881				t.Errorf("want out=%v; got %v", expected, out)
1882			}
1883		})
1884
1885		t.Run("interface types", func(t *testing.T) {
1886			m := func(field, col string, v interface{}) string {
1887				if _, ok := v.(string); ok {
1888					return strings.ToUpper(field)
1889				}
1890				if _, ok := v.(int); ok {
1891					return "100"
1892				}
1893				t.Fatalf("expected v to be a string, was %T", v)
1894				return field
1895			}
1896
1897			data := []byte("F1,F2,F3,F4,F5,F6\na,b,3,4,5,6")
1898			dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1899			if err != nil {
1900				t.Fatalf("want err=nil; got %v", err)
1901			}
1902			dec.Map = m
1903
1904			var out = struct {
1905				F1 interface{}
1906				F2 *interface{}
1907				F3 interface{}
1908				F4 interface{}
1909				F5 interface{}
1910				F6 *interface{}
1911			}{
1912				F3: int(0), // initialize an interface with a different type
1913				F4: pint(0),
1914				F5: (*int)(nil),
1915				F6: pinterface(ppint(0)),
1916			}
1917			if err := dec.Decode(&out); err != nil {
1918				t.Errorf("want err=nil; got %v", err)
1919			}
1920
1921			if out.F1 != "A" {
1922				t.Errorf("expected F1=A got: %v", out.F1)
1923			}
1924			if *out.F2 != "B" {
1925				t.Errorf("expected F2=B got: %v", *out.F2)
1926			}
1927			if out.F3 != "3" {
1928				t.Errorf("expected F3=\"3\" got: %v", out.F3)
1929			}
1930
1931			f4, ok := out.F4.(*int)
1932			if !ok || f4 == nil {
1933				t.Error("expected F4 to be non nil int ptr")
1934				return
1935			}
1936			if *f4 != 100 {
1937				t.Errorf("expected F4=100 got: %v", f4)
1938			}
1939
1940			if out.F5 != "5" {
1941				t.Errorf("expected F5=\"5\" got: %v", out.F5)
1942			}
1943
1944			f6, ok := (*out.F6).(**int)
1945			if !ok || f4 == nil {
1946				t.Error("expected F6 to be non nil int ptr")
1947				return
1948			}
1949			if **f6 != 100 {
1950				t.Errorf("expected F4=100 got: %v", f6)
1951			}
1952		})
1953
1954		t.Run("receives a proper column name", func(t *testing.T) {
1955			const val = "magic_column"
1956			m := func(field, col string, v interface{}) string {
1957				if col == "F2" {
1958					return val
1959				}
1960				return field
1961			}
1962
1963			data := []byte("F1,F2\na,b")
1964			dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1965			if err != nil {
1966				t.Fatalf("want err=nil; got %v", err)
1967			}
1968			dec.Map = m
1969
1970			var out = struct {
1971				F1 string
1972				F2 string
1973			}{}
1974			if err := dec.Decode(&out); err != nil {
1975				t.Errorf("want err=nil; got %v", err)
1976			}
1977
1978			if out.F1 != "a" {
1979				t.Errorf("expected F1=a got: %v", out.F1)
1980			}
1981			if out.F2 != val {
1982				t.Errorf("expected F2=%s got: %v", val, out.F1)
1983			}
1984		})
1985	})
1986
1987	t.Run("decoding into specific values", func(t *testing.T) {
1988		setup := func(t *testing.T) *Decoder {
1989			data := []byte("String,Int\na,1")
1990			dec, err := NewDecoder(newCSVReader(bytes.NewReader(data)))
1991			if err != nil {
1992				t.Fatalf("want err=nil; got %v", err)
1993			}
1994			return dec
1995		}
1996
1997		t.Run("wrapped in interfaces", func(t *testing.T) {
1998			dec := setup(t)
1999
2000			var out *TypeG
2001			var ii interface{} = &out
2002			var i interface{} = ii
2003			if err := dec.Decode(&i); err != nil {
2004				t.Errorf("want err=nil; got %v", err)
2005			}
2006			if out == nil {
2007				t.Fatal("want out to not be nil")
2008			}
2009			if expected := (TypeG{String: "a", Int: 1}); *out != expected {
2010				t.Errorf("want expected=%v; got %v", expected, *out)
2011			}
2012		})
2013
2014		t.Run("wrapped in interfaces #2", func(t *testing.T) {
2015			dec := setup(t)
2016
2017			var out *TypeG
2018			var ii interface{} = &out
2019			var i interface{} = &ii
2020			if err := dec.Decode(&i); err != nil {
2021				t.Errorf("want err=nil; got %v", err)
2022			}
2023			if out == nil {
2024				t.Fatal("want out to not be nil")
2025			}
2026			if expected := (TypeG{String: "a", Int: 1}); *out != expected {
2027				t.Errorf("want expected=%v; got %v", expected, *out)
2028			}
2029		})
2030
2031		t.Run("wrapped in interfaces not ptr", func(t *testing.T) {
2032			dec := setup(t)
2033
2034			var out *TypeG
2035			var ii interface{} = out
2036			var i interface{} = ii
2037
2038			expected := &InvalidDecodeError{Type: reflect.TypeOf(&TypeG{})}
2039			if err := dec.Decode(i); !reflect.DeepEqual(err, expected) {
2040				t.Errorf("want err=%v; got %v", expected, err)
2041			}
2042		})
2043
2044		t.Run("wrapped in interface non ptr value", func(t *testing.T) {
2045			dec := setup(t)
2046
2047			var out TypeG
2048			var ii interface{} = &out
2049			var i interface{} = ii
2050			if err := dec.Decode(&i); err != nil {
2051				t.Errorf("want err=nil; got %v", err)
2052			}
2053			if expected := (TypeG{String: "a", Int: 1}); out != expected {
2054				t.Errorf("want expected=%v; got %v", expected, out)
2055			}
2056		})
2057
2058		t.Run("interface to interface", func(t *testing.T) {
2059			dec := setup(t)
2060
2061			var ii interface{}
2062			var i interface{} = &ii
2063
2064			expected := &InvalidDecodeError{Type: reflect.TypeOf((*interface{})(nil))}
2065			if err := dec.Decode(&i); !reflect.DeepEqual(err, expected) {
2066				t.Errorf("want err=%v; got %v", expected, err)
2067			}
2068		})
2069
2070		t.Run("interface to nil interface", func(t *testing.T) {
2071			dec := setup(t)
2072
2073			var ii *interface{}
2074			var i interface{} = ii
2075
2076			expected := &InvalidDecodeError{Type: reflect.TypeOf((*interface{})(nil))}
2077			if err := dec.Decode(&i); !reflect.DeepEqual(err, expected) {
2078				t.Errorf("want err=%v; got %v", expected, err)
2079			}
2080		})
2081
2082		t.Run("nil ptr value", func(t *testing.T) {
2083			dec := setup(t)
2084
2085			var out *TypeG
2086			expected := &InvalidDecodeError{Type: reflect.TypeOf(&TypeG{})}
2087			if err := dec.Decode(out); !reflect.DeepEqual(err, expected) {
2088				t.Errorf("want err=%v; got %v", expected, err)
2089			}
2090		})
2091
2092		t.Run("nil ptr value ptr", func(t *testing.T) {
2093			dec := setup(t)
2094
2095			var out *TypeG
2096			if err := dec.Decode(&out); err != nil {
2097				t.Errorf("want err=nil; got %v", err)
2098			}
2099			if out == nil {
2100				t.Fatal("want out to not be nil")
2101			}
2102			if expected := (TypeG{String: "a", Int: 1}); *out != expected {
2103				t.Errorf("want expected=%v; got %v", expected, *out)
2104			}
2105		})
2106
2107		t.Run("nil double ptr value", func(t *testing.T) {
2108			dec := setup(t)
2109
2110			var out **TypeG
2111
2112			expected := &InvalidDecodeError{Type: reflect.TypeOf(out)}
2113			if err := dec.Decode(out); !reflect.DeepEqual(err, expected) {
2114				t.Errorf("want err=%v; got %v", expected, err)
2115			}
2116		})
2117
2118		t.Run("nil double ptr value ptr", func(t *testing.T) {
2119			dec := setup(t)
2120
2121			var out **TypeG
2122			if err := dec.Decode(&out); err != nil {
2123				t.Errorf("want err=nil; got %v", err)
2124			}
2125			if out == nil {
2126				t.Fatal("want out to not be nil")
2127			}
2128			if expected := (TypeG{String: "a", Int: 1}); **out != expected {
2129				t.Errorf("want expected=%v; got %v", expected, **out)
2130			}
2131		})
2132
2133		t.Run("non ptr value ptr", func(t *testing.T) {
2134			dec := setup(t)
2135
2136			var out TypeG
2137			if err := dec.Decode(&out); err != nil {
2138				t.Errorf("want err=nil; got %v", err)
2139			}
2140			if expected := (TypeG{String: "a", Int: 1}); out != expected {
2141				t.Errorf("want expected=%v; got %v", expected, out)
2142			}
2143		})
2144	})
2145
2146	t.Run("decode slice", func(t *testing.T) {
2147		csvr := csv.NewReader(strings.NewReader("String,int\nfirst,1\nsecond,2"))
2148		dec, err := NewDecoder(csvr)
2149		if err != nil {
2150			t.Fatalf("want err == nil; got %v", err)
2151		}
2152
2153		var data []TypeI
2154		if err := dec.Decode(&data); err != nil {
2155			t.Errorf("want err=nil; got %v", err)
2156		}
2157
2158		if len(data) != 2 {
2159			t.Fatalf("want len=2; got %d", len(data))
2160		}
2161
2162		if err := dec.Decode(&data); err != io.EOF {
2163			t.Errorf("want err=EOF; got %v", err)
2164		}
2165	})
2166
2167	t.Run("decode slice - error", func(t *testing.T) {
2168		csvr := csv.NewReader(strings.NewReader("String,int\nfirst,1\nsecond,notint\nthird,3"))
2169		dec, err := NewDecoder(csvr)
2170		if err != nil {
2171			t.Fatalf("want err == nil; got %v", err)
2172		}
2173
2174		var data []TypeI
2175		if err := dec.Decode(&data); err == nil {
2176			t.Errorf("want err!=nil; got %v", err)
2177		}
2178
2179		if len(data) != 2 {
2180			t.Errorf("want len=2; got %d", len(data))
2181		}
2182
2183		if data[1].String != "second" {
2184			t.Errorf("want String=second; got %s", data[1].String)
2185		}
2186		if data[1].Int != 0 {
2187			t.Errorf("want Int=0; got %d", data[1].Int)
2188		}
2189	})
2190
2191	t.Run("decode array", func(t *testing.T) {
2192		csvr := csv.NewReader(strings.NewReader("String,int\nfirst,1\nsecond,2"))
2193		dec, err := NewDecoder(csvr)
2194		if err != nil {
2195			t.Fatalf("want err == nil; got %v", err)
2196		}
2197
2198		var data [1]TypeI
2199		if err := dec.Decode(&data); err != nil {
2200			t.Errorf("want err=nil; got %v", err)
2201		}
2202
2203		if expected := (TypeI{String: "first", Int: 1}); data[0] != expected {
2204			t.Errorf("want %v; got %v", expected, data[0])
2205		}
2206
2207		if err := dec.Decode(&data); err != nil {
2208			t.Errorf("want err=nil; got %v", err)
2209		}
2210
2211		if expected := (TypeI{String: "second", Int: 2}); data[0] != expected {
2212			t.Errorf("want %v; got %v", expected, data[0])
2213		}
2214
2215		if err := dec.Decode(&data); err != io.EOF {
2216			t.Errorf("want err=EOF; got %v", err)
2217		}
2218	})
2219
2220	t.Run("decode array - error", func(t *testing.T) {
2221		csvr := csv.NewReader(strings.NewReader("String,int\nfirst,1\nsecond,notint"))
2222		dec, err := NewDecoder(csvr)
2223		if err != nil {
2224			t.Fatalf("want err == nil; got %v", err)
2225		}
2226
2227		var data [2]TypeI
2228		if err := dec.Decode(&data); err == nil {
2229			t.Errorf("want err!=nil; got %v", err)
2230		}
2231
2232		if data[1].String != "second" {
2233			t.Errorf("want String=second; got %s", data[1].String)
2234		}
2235		if data[1].Int != 0 {
2236			t.Errorf("want Int=0; got %d", data[1].Int)
2237		}
2238	})
2239
2240	t.Run("register panics", func(t *testing.T) {
2241		dec, err := NewDecoder(csv.NewReader(nil), "foo")
2242		if err != nil {
2243			panic(err)
2244		}
2245
2246		fixtures := []struct {
2247			desc string
2248			arg  interface{}
2249		}{
2250			{
2251				desc: "not a func",
2252				arg:  1,
2253			},
2254			{
2255				desc: "nil",
2256				arg:  nil,
2257			},
2258			{
2259				desc: "T == empty interface",
2260				arg:  func([]byte, interface{}) error { return nil },
2261			},
2262			{
2263				desc: "first in not bytes",
2264				arg:  func(int, int) error { return nil },
2265			},
2266			{
2267				desc: "out not error",
2268				arg:  func([]byte, *int) int { return 0 },
2269			},
2270			{
2271				desc: "func with one in value",
2272				arg:  func(int) error { return nil },
2273			},
2274			{
2275				desc: "func with no returns",
2276				arg:  func([]byte, int) {},
2277			},
2278		}
2279
2280		for _, f := range fixtures {
2281			t.Run(f.desc, func(t *testing.T) {
2282				var e interface{}
2283				func() {
2284					defer func() {
2285						e = recover()
2286					}()
2287					dec.Register(f.arg)
2288				}()
2289
2290				if e == nil {
2291					t.Error("Register was supposed to panic but it didnt")
2292				}
2293				t.Log(e)
2294			})
2295		}
2296
2297		t.Run("already registered", func(t *testing.T) {
2298			f := func([]byte, int) error { return nil }
2299			dec.Register(f)
2300
2301			var e interface{}
2302			func() {
2303				defer func() {
2304					e = recover()
2305				}()
2306				dec.Register(f)
2307			}()
2308
2309			if e == nil {
2310				t.Error("Register was supposed to panic but it didnt")
2311			}
2312			t.Log(e)
2313		})
2314	})
2315}
2316
2317func BenchmarkDecode(b *testing.B) {
2318	type A struct {
2319		A int     `csv:"a"`
2320		B float64 `csv:"b"`
2321		C string  `csv:"c"`
2322		D int64   `csv:"d"`
2323		E int8    `csv:"e"`
2324		F float32 `csv:"f"`
2325		G float32 `csv:"g"`
2326		H float32 `csv:"h"`
2327		I string  `csv:"i"`
2328		J int     `csv:"j"`
2329	}
2330
2331	header := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
2332	record := []string{"1", "2.5", "xD", "6", "7", "8", "9", "10", "lol", "10"}
2333
2334	fixtures := []struct {
2335		desc string
2336		len  int
2337	}{
2338		{"10 field struct 1 record", 1},
2339		{"10 field struct 10 records", 10},
2340		{"10 field struct 100 records", 100},
2341		{"10 field struct 1000 records", 1000},
2342		{"10 field struct 10000 records", 10000},
2343	}
2344
2345	for _, f := range fixtures {
2346		var records [][]string
2347		for i := 0; i < f.len; i++ {
2348			records = append(records, record)
2349		}
2350
2351		b.Run(f.desc, func(b *testing.B) {
2352			for i := 0; i < b.N; i++ {
2353				b.StopTimer()
2354				dec, err := NewDecoder(NewReader(records...), header...)
2355				if err != nil {
2356					b.Fatal(err)
2357				}
2358				var a A
2359				b.StartTimer()
2360
2361				for {
2362					if err := dec.Decode(&a); err == io.EOF {
2363						break
2364					} else if err != nil {
2365						b.Fatal(err)
2366					}
2367				}
2368			}
2369		})
2370	}
2371
2372	b.Run("10 field struct first decode", func(b *testing.B) {
2373		for i := 0; i < b.N; i++ {
2374			b.StopTimer()
2375			dec, err := NewDecoder(NewReader(record), header...)
2376			if err != nil {
2377				b.Fatal(err)
2378			}
2379
2380			var a A
2381			b.StartTimer()
2382
2383			if err := dec.Decode(&a); err != nil {
2384				b.Fatal(err)
2385			}
2386		}
2387	})
2388
2389	b.Run("10 field struct second decode", func(b *testing.B) {
2390		for i := 0; i < b.N; i++ {
2391			b.StopTimer()
2392			r, err := NewDecoder(NewReader(record, record), header...)
2393			if err != nil {
2394				b.Fatal(err)
2395			}
2396
2397			var a A
2398			if err := r.Decode(&a); err != nil {
2399				b.Fatal(err)
2400			}
2401			a = A{}
2402			b.StartTimer()
2403
2404			if err := r.Decode(&a); err != nil {
2405				b.Fatal(err)
2406			}
2407		}
2408	})
2409}
2410
2411type reader struct {
2412	records [][]string
2413	i       int
2414}
2415
2416func NewReader(records ...[]string) Reader {
2417	return &reader{records, 0}
2418}
2419
2420func (r *reader) Read() ([]string, error) {
2421	if r.i >= len(r.records) {
2422		return nil, io.EOF
2423	}
2424	r.i++
2425	return r.records[r.i-1], nil
2426}
2427