func NewGenericDatumWriter() *GenericDatumWriter {
	return &GenericDatumWriter{}
}
NewGenericDatumWriter creates a new GenericDatumWriter.
package avro
import (
	"errors"
	"fmt"
	"reflect"
)
type Marshaler interface {
	MarshalAvro(enc Encoder) error
}
type DatumWriter interface {
	Write(obj interface{}, enc Encoder) error
}
func NewDatumWriter(schema Schema) DatumWriter {
	if schema == nil {
		panic("NewDatumWriter: Must provide a non-nil schema.")
	}
	return &anyDatumWriter{
		sdr: SpecificDatumWriter{schema: schema},
		gdr: GenericDatumWriter{schema: schema},
	}
}
type anyDatumWriter struct {
	sdr SpecificDatumWriter
	gdr GenericDatumWriter
}
var errNilWrite = errors.New("DatumWriter.Write: provided a nil GenericRecord")
func (w *anyDatumWriter) Write(obj interface{}, enc Encoder) error {
	switch v := obj.(type) {
	case *GenericRecord:
		return w.gdr.Write(obj, enc)
	case **GenericRecord:
		if v == nil || *v == nil {
			return errNilWrite
		}
		return w.gdr.Write(*v, enc)
	default:
		return w.sdr.Write(obj, enc)
	}
}
var _ DatumWriter = (*GenericDatumWriter)(nil)
var _ DatumWriter = (*SpecificDatumWriter)(nil)
type SpecificDatumWriter struct {
	schema Schema
}
func NewSpecificDatumWriter() *SpecificDatumWriter {
	return &SpecificDatumWriter{}
}
func (writer *SpecificDatumWriter) SetSchema(schema Schema) DatumWriter {
	writer.schema = schema
	return writer
}
func (writer *SpecificDatumWriter) Write(obj interface{}, enc Encoder) error {
	if writer, ok := obj.(Marshaler); ok {
		return writer.MarshalAvro(enc)
	}
	rv := reflect.ValueOf(obj)
	if writer.schema == nil {
		return ErrSchemaNotSet
	}
	return writer.write(rv, enc, writer.schema)
}
func (writer *SpecificDatumWriter) write(v reflect.Value, enc Encoder, s Schema) error {
	switch s.Type() {
	case Null:
	case Boolean:
		return writer.writeBoolean(v, enc, s)
	case Int:
		return writer.writeInt(v, enc, s)
	case Long:
		return writer.writeLong(v, enc, s)
	case Float:
		return writer.writeFloat(v, enc, s)
	case Double:
		return writer.writeDouble(v, enc, s)
	case Bytes:
		return writer.writeBytes(v, enc, s)
	case String:
		return writer.writeString(v, enc, s)
	case Array:
		return writer.writeArray(v, enc, s)
	case Map:
		return writer.writeMap(v, enc, s)
	case Enum:
		return writer.writeEnum(v, enc, s)
	case Union:
		return writer.writeUnion(v, enc, s)
	case Fixed:
		return writer.writeFixed(v, enc, s)
	case Record:
		return writer.writeRecord(v, enc, s)
	case Recursive:
		return writer.writeRecord(v, enc, s.(*RecursiveSchema).Actual)
	}
	return nil
}
func (writer *SpecificDatumWriter) writeBoolean(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid boolean value: %v", v.Interface())
	}
	enc.WriteBoolean(v.Interface().(bool))
	return nil
}
func (writer *SpecificDatumWriter) writeInt(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid int value: %v", v.Interface())
	}
	enc.WriteInt(v.Interface().(int32))
	return nil
}
func (writer *SpecificDatumWriter) writeLong(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid long value: %v", v.Interface())
	}
	enc.WriteLong(v.Interface().(int64))
	return nil
}
func (writer *SpecificDatumWriter) writeFloat(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid float value: %v", v.Interface())
	}
	enc.WriteFloat(v.Interface().(float32))
	return nil
}
func (writer *SpecificDatumWriter) writeDouble(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid double value: %v", v.Interface())
	}
	enc.WriteDouble(v.Interface().(float64))
	return nil
}
func (writer *SpecificDatumWriter) writeBytes(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid bytes value: %v", v.Interface())
	}
	enc.WriteBytes(v.Interface().([]byte))
	return nil
}
func (writer *SpecificDatumWriter) writeString(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid string value: %v", v.Interface())
	}
	enc.WriteString(v.Interface().(string))
	return nil
}
func (writer *SpecificDatumWriter) writeArray(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid array value: %v", v.Interface())
	}
	if v.Len() == 0 {
		enc.WriteArrayNext(0)
		return nil
	}
	enc.WriteArrayStart(int64(v.Len()))
	for i := 0; i < v.Len(); i++ {
		if err := writer.write(v.Index(i), enc, s.(*ArraySchema).Items); err != nil {
			return err
		}
	}
	enc.WriteArrayNext(0)
	return nil
}
func (writer *SpecificDatumWriter) writeMap(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid map value: %v", v.Interface())
	}
	if v.Len() == 0 {
		enc.WriteMapNext(0)
		return nil
	}
	enc.WriteMapStart(int64(v.Len()))
	for _, key := range v.MapKeys() {
		err := writer.writeString(key, enc, &StringSchema{})
		if err != nil {
			return err
		}
		if err = writer.write(v.MapIndex(key), enc, s.(*MapSchema).Values); err != nil {
			return err
		}
	}
	enc.WriteMapNext(0)
	return nil
}
func (writer *SpecificDatumWriter) writeEnum(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Invalid enum value: %v", v.Interface())
	}
	enc.WriteInt(v.Interface().(*GenericEnum).GetIndex())
	return nil
}
func (writer *SpecificDatumWriter) writeUnion(v reflect.Value, enc Encoder, s Schema) error {
	unionSchema := s.(*UnionSchema)
	index := unionSchema.GetType(v)
	if unionSchema.Types == nil || index < 0 || index >= len(unionSchema.Types) {
		return fmt.Errorf("Invalid union value: %v", v.Interface())
	}
	enc.WriteLong(int64(index))
	return writer.write(v, enc, unionSchema.Types[index])
}
func (writer *SpecificDatumWriter) writeFixed(v reflect.Value, enc Encoder, s Schema) error {
	fs := s.(*FixedSchema)
	if !fs.Validate(v) {
		return fmt.Errorf("Invalid fixed value: %v", v.Interface())
	}
	enc.WriteRaw(v.Interface().([]byte))
	return nil
}
func (writer *SpecificDatumWriter) writeRecord(v reflect.Value, enc Encoder, s Schema) error {
	if !s.Validate(v) {
		return fmt.Errorf("Encoding Record %s: Invalid record value: %v", s.GetName(), v.Interface())
	}
	rs := assertRecordSchema(s)
	for i := range rs.Fields {
		schemaField := rs.Fields[i]
		field, err := findField(v, schemaField.Name)
		if err != nil {
			return err
		}
		if err := writer.write(field, enc, schemaField.Type); err != nil {
			return err
		}
	}
	return nil
}
type GenericDatumWriter struct {
	schema Schema
}