func Unmarshal(data []byte, v interface{}) error {
	rv := reflect.ValueOf(v)
	if (rv.Kind() != reflect.Ptr && rv.Kind() != reflect.Map) || rv.IsNil() {
		return ErrUnsupportedType
	}
	if rv.Kind() == reflect.Ptr {
		rvElem := rv.Elem()
		switch rvElem.Kind() {
		case reflect.Struct:
			return unmarshalStruct(data, rvElem)
		case reflect.Slice:
			return unmarshalSlice(data, rvElem)
		}
	}
	if mapper, ok := v.(map[string]interface{}); ok {
		return unmarshalMapper(data, mapper)
	}
	return ErrUnsupportedType
}
Unmarshal parses the CNAB-encoded data and stores the result in the value
pointed to by v. Accepted types of v are: *struct, *[]struct or
map[string]interface{}.

The following struct field types are supported: string, bool, int, int8,
int16, int32, int64, uint, uint8, uint16, uint23, uint64, float32, float64,
gocnab.Unmarshaler and encoding.TextUnmarshaler.

When parsing a full CNAB file we recommend using the map type (mapper) to
fill different lines into the correct types. Usually the CNAB prefix
determinate the type used, so the mapper key will be the prefix, and the
mapper value is the pointer to the type that you're filling. For example, if
we have a CNAB file where the starter character determinate the type, and for
"0" is header, "1" is the content line (can repeat many times) and "2" is the
footer, we could have the following code to unmarshal:

header := struct{ A int `cnab:1,10` }{}
content := []struct{ B string `cnab:1,10` }{}
footer := struct{ C bool `cnab:1,2` }{}

cnab.Unmarshal(data, map[string]interface{}{
"0": &header,
"1": &content,
"2": &footer,
})
package gocnab
import (
	"bytes"
	"encoding"
	"errors"
	"fmt"
	"reflect"
	"strconv"
	"strings"
)
const LineBreak = "\r\n"
const FinalControlCharacter = "\x1A"
var (
	ErrUnsupportedType = errors.New("gocnab: unsupported type")
	ErrInvalidFieldTagFormat = errors.New("invalid field tag format")
	ErrInvalidFieldTagBeginRange = errors.New("invalid begin range in cnab tag")
	ErrInvalidFieldTagEndRange = errors.New("invalid end range in cnab tag")
	ErrInvalidFieldTagRange = errors.New("invalid range in cnab tag")
)
type MarshalOptions struct {
	addFinalControlCharacter bool
}
type MarshalOptionFunc func(*MarshalOptions)
func WithFinalControlCharacter(enabled bool) MarshalOptionFunc {
	return MarshalOptionFunc(func(options *MarshalOptions) {
		options.addFinalControlCharacter = enabled
	})
}
func Marshal240(vs ...interface{}) ([]byte, error) {
	return marshal(240, vs...)
}
func Marshal400(vs ...interface{}) ([]byte, error) {
	return marshal(400, vs...)
}
func Marshal500(vs ...interface{}) ([]byte, error) {
	return marshal(500, vs...)
}
func marshal(lineSize int, vs ...interface{}) ([]byte, error) {
	options := MarshalOptions{
		addFinalControlCharacter: true,
	}
	var i int
	for _, v := range vs {
		if optFunc, ok := v.(MarshalOptionFunc); ok {
			optFunc(&options)
		} else {
			vs[i] = v
			i++
		}
	}
	vs = vs[:i]
	var cnab []byte
	for i, v := range vs {
		cnabLine, err := marshalLine(lineSize, v)
		if err != nil {
			return nil, err
		}
		cnab = append(cnab, cnabLine...)
		if len(vs) > 1 && i < len(vs)-1 {
			cnab = append(cnab, []byte(LineBreak)...)
		}
	}
	if options.addFinalControlCharacter && len(vs) > 1 && cnab != nil {
		cnab = append(cnab, []byte(FinalControlCharacter)...)
	}
	return cnab, nil
}
func marshalLine(lineSize int, v interface{}) ([]byte, error) {
	rv := reflect.ValueOf(v)
	switch rv.Kind() {
	case reflect.Struct:
		cnab := []byte(strings.Repeat(" ", lineSize))
		if err := marshalStruct(cnab, rv); err != nil {
			return nil, err
		}
		return cnab, nil
	case reflect.Slice:
		var cnab []byte
		for i := 0; i < rv.Len(); i++ {
			line := []byte(strings.Repeat(" ", lineSize))
			if err := marshalStruct(line, rv.Index(i)); err != nil {
				return nil, err
			}
			cnab = append(cnab, line...)
			if i < rv.Len()-1 {
				cnab = append(cnab, []byte(LineBreak)...)
			}
		}
		return cnab, nil
	}
	return nil, ErrUnsupportedType
}
func marshalStruct(data []byte, v reflect.Value) error {
	structType := v.Type()
	for i := 0; i < structType.NumField(); i++ {
		structField := structType.Field(i)
		begin, end, err := parseCNABFieldTag(structField, len(data))
		if err != nil {
			return FieldError{
				Field: structField.Name,
				Err:   err,
			}
		}
		if begin == 0 && end == 0 {
			continue
		}
		if err = marshalField(data, v.FieldByName(structField.Name), begin, end); err != nil {
			return FieldError{
				Field: structField.Name,
				Err:   err,
			}
		}
	}
	return nil
}
func marshalField(data []byte, v reflect.Value, begin, end int) error {
	cnabFieldSize := end - begin
	switch v.Kind() {
	case reflect.String:
		fieldContent := v.Interface().(string)
		setFieldContent(data, fieldContent, begin, end)
		return nil
	case reflect.Bool:
		fieldContent := v.Interface().(bool)
		var convertedFieldContent string
		if fieldContent {
			convertedFieldContent = "1"
		} else {
			convertedFieldContent = "0"
		}
		convertedFieldContent = fmt.Sprintf("%0"+strconv.Itoa(cnabFieldSize)+"s", convertedFieldContent)
		setFieldContent(data, convertedFieldContent, begin, end)
		return nil
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		fieldContent := fmt.Sprintf("%0"+strconv.Itoa(cnabFieldSize)+"d", v.Int())
		setFieldContent(data, fieldContent, begin, end)
		return nil
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		fieldContent := fmt.Sprintf("%0"+strconv.Itoa(cnabFieldSize)+"d", v.Uint())
		setFieldContent(data, fieldContent, begin, end)
		return nil
	case reflect.Float32, reflect.Float64:
		fieldContent := fmt.Sprintf("%0"+strconv.Itoa(cnabFieldSize)+".2f", v.Float())
		fieldContent = "0" + strings.Replace(fieldContent, ".", "", -1)
		setFieldContent(data, fieldContent, begin, end)
		return nil
	}
	marshalerType := reflect.TypeOf((*Marshaler)(nil)).Elem()
	if v.Type().Implements(marshalerType) {
		fieldContent, err := v.Interface().(Marshaler).MarshalCNAB()
		if err != nil {
			return err
		}
		setFieldContent(data, string(fieldContent), begin, end)
		return nil
	}
	textMarshalerType := reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem()
	if v.Type().Implements(textMarshalerType) {
		fieldContent, err := v.Interface().(encoding.TextMarshaler).MarshalText()
		if err != nil {
			return err
		}
		setFieldContent(data, string(fieldContent), begin, end)
		return nil
	}
	return ErrUnsupportedType
}
func setFieldContent(data []byte, fieldContent string, begin, end int) {
	cnabFieldSize := end - begin
	if len(fieldContent) > cnabFieldSize {
		fieldContent = fieldContent[0:cnabFieldSize]
	} else if len(fieldContent) < cnabFieldSize {
		fieldContent = fieldContent + strings.Repeat(" ", cnabFieldSize-len(fieldContent))
	}
	copy(data[begin:], strings.ToUpper(fieldContent))
}