package parquet

import (
	
	
	
	
	
	
	

	
	
	
)

// Kind is an enumeration type representing the physical types supported by the
// parquet type system.
type Kind int8

const (
	Boolean           Kind = Kind(format.Boolean)
	Int32             Kind = Kind(format.Int32)
	Int64             Kind = Kind(format.Int64)
	Int96             Kind = Kind(format.Int96)
	Float             Kind = Kind(format.Float)
	Double            Kind = Kind(format.Double)
	ByteArray         Kind = Kind(format.ByteArray)
	FixedLenByteArray Kind = Kind(format.FixedLenByteArray)
)

// String returns a human-readable representation of the physical type.
func ( Kind) () string { return format.Type().String() }

// Value constructs a value from k and v.
//
// The method panics if the data is not a valid representation of the value
// kind; for example, if the kind is Int32 but the data is not 4 bytes long.
func ( Kind) ( []byte) Value {
	,  := parseValue(, )
	if  != nil {
		panic()
	}
	return 
}

// The Type interface represents logical types of the parquet type system.
//
// Types are immutable and therefore safe to access from multiple goroutines.
type Type interface {
	// Returns a human-readable representation of the parquet type.
	String() string

	// Returns the Kind value representing the underlying physical type.
	//
	// The method panics if it is called on a group type.
	Kind() Kind

	// For integer and floating point physical types, the method returns the
	// size of values in bits.
	//
	// For fixed-length byte arrays, the method returns the size of elements
	// in bytes.
	//
	// For other types, the value is zero.
	Length() int

	// Returns an estimation of the number of bytes required to hold the given
	// number of values of this type in memory.
	//
	// The method returns zero for group types.
	EstimateSize(numValues int) int

	// Returns an estimation of the number of values of this type that can be
	// held in the given byte size.
	//
	// The method returns zero for group types.
	EstimateNumValues(size int) int

	// Compares two values and returns a negative integer if a < b, positive if
	// a > b, or zero if a == b.
	//
	// The values' Kind must match the type, otherwise the result is undefined.
	//
	// The method panics if it is called on a group type.
	Compare(a, b Value) int

	// ColumnOrder returns the type's column order. For group types, this method
	// returns nil.
	//
	// The order describes the comparison logic implemented by the Less method.
	//
	// As an optimization, the method may return the same pointer across
	// multiple calls. Applications must treat the returned value as immutable,
	// mutating the value will result in undefined behavior.
	ColumnOrder() *format.ColumnOrder

	// Returns the physical type as a *format.Type value. For group types, this
	// method returns nil.
	//
	// As an optimization, the method may return the same pointer across
	// multiple calls. Applications must treat the returned value as immutable,
	// mutating the value will result in undefined behavior.
	PhysicalType() *format.Type

	// Returns the logical type as a *format.LogicalType value. When the logical
	// type is unknown, the method returns nil.
	//
	// As an optimization, the method may return the same pointer across
	// multiple calls. Applications must treat the returned value as immutable,
	// mutating the value will result in undefined behavior.
	LogicalType() *format.LogicalType

	// Returns the logical type's equivalent converted type. When there are
	// no equivalent converted type, the method returns nil.
	//
	// As an optimization, the method may return the same pointer across
	// multiple calls. Applications must treat the returned value as immutable,
	// mutating the value will result in undefined behavior.
	ConvertedType() *deprecated.ConvertedType

	// Creates a column indexer for values of this type.
	//
	// The size limit is a hint to the column indexer that it is allowed to
	// truncate the page boundaries to the given size. Only BYTE_ARRAY and
	// FIXED_LEN_BYTE_ARRAY types currently take this value into account.
	//
	// A value of zero or less means no limits.
	//
	// The method panics if it is called on a group type.
	NewColumnIndexer(sizeLimit int) ColumnIndexer

	// Creates a row group buffer column for values of this type.
	//
	// Column buffers are created using the index of the column they are
	// accumulating values in memory for (relative to the parent schema),
	// and the size of their memory buffer.
	//
	// The application may give an estimate of the number of values it expects
	// to write to the buffer as second argument. This estimate helps set the
	// initialize buffer capacity but is not a hard limit, the underlying memory
	// buffer will grown as needed to allow more values to be written. Programs
	// may use the Size method of the column buffer (or the parent row group,
	// when relevant) to determine how many bytes are being used, and perform a
	// flush of the buffers to a storage layer.
	//
	// The method panics if it is called on a group type.
	NewColumnBuffer(columnIndex, numValues int) ColumnBuffer

	// Creates a dictionary holding values of this type.
	//
	// The dictionary retains the data buffer, it does not make a copy of it.
	// If the application needs to share ownership of the memory buffer, it must
	// ensure that it will not be modified while the page is in use, or it must
	// make a copy of it prior to creating the dictionary.
	//
	// The method panics if the data type does not correspond to the parquet
	// type it is called on.
	NewDictionary(columnIndex, numValues int, data encoding.Values) Dictionary

	// Creates a page belonging to a column at the given index, backed by the
	// data buffer.
	//
	// The page retains the data buffer, it does not make a copy of it. If the
	// application needs to share ownership of the memory buffer, it must ensure
	// that it will not be modified while the page is in use, or it must make a
	// copy of it prior to creating the page.
	//
	// The method panics if the data type does not correspond to the parquet
	// type it is called on.
	NewPage(columnIndex, numValues int, data encoding.Values) Page

	// Creates an encoding.Values instance backed by the given buffers.
	//
	// The offsets is only used by BYTE_ARRAY types, where it represents the
	// positions of each variable length value in the values buffer.
	//
	// The following expression creates an empty instance for any type:
	//
	//		values := typ.NewValues(nil, nil)
	//
	// The method panics if it is called on group types.
	NewValues(values []byte, offsets []uint32) encoding.Values

	// Assuming the src buffer contains PLAIN encoded values of the type it is
	// called on, applies the given encoding and produces the output to the dst
	// buffer passed as first argument by dispatching the call to one of the
	// encoding methods.
	Encode(dst []byte, src encoding.Values, enc encoding.Encoding) ([]byte, error)

	// Assuming the src buffer contains values encoding in the given encoding,
	// decodes the input and produces the encoded values into the dst output
	// buffer passed as first argument by dispatching the call to one of the
	// encoding methods.
	Decode(dst encoding.Values, src []byte, enc encoding.Encoding) (encoding.Values, error)

	// Returns an estimation of the output size after decoding the values passed
	// as first argument with the given encoding.
	//
	// For most types, this is similar to calling EstimateSize with the known
	// number of encoded values. For variable size types, using this method may
	// provide a more precise result since it can inspect the input buffer.
	EstimateDecodeSize(numValues int, src []byte, enc encoding.Encoding) int

	// Assigns a Parquet value to a Go value. Returns an error if assignment is
	// not possible. The source Value must be an expected logical type for the
	// receiver. This can be accomplished using ConvertValue.
	AssignValue(dst reflect.Value, src Value) error

	// Convert a Parquet Value of the given Type into a Parquet Value that is
	// compatible with the receiver. The returned Value is suitable to be passed
	// to AssignValue.
	ConvertValue(val Value, typ Type) (Value, error)
}

var (
	BooleanType   Type = booleanType{}
	Int32Type     Type = int32Type{}
	Int64Type     Type = int64Type{}
	Int96Type     Type = int96Type{}
	FloatType     Type = floatType{}
	DoubleType    Type = doubleType{}
	ByteArrayType Type = byteArrayType{}
)

// In the current parquet version supported by this library, only type-defined
// orders are supported.
var typeDefinedColumnOrder = format.ColumnOrder{
	TypeOrder: new(format.TypeDefinedOrder),
}

var physicalTypes = [...]format.Type{
	0: format.Boolean,
	1: format.Int32,
	2: format.Int64,
	3: format.Int96,
	4: format.Float,
	5: format.Double,
	6: format.ByteArray,
	7: format.FixedLenByteArray,
}

var convertedTypes = [...]deprecated.ConvertedType{
	0:  deprecated.UTF8,
	1:  deprecated.Map,
	2:  deprecated.MapKeyValue,
	3:  deprecated.List,
	4:  deprecated.Enum,
	5:  deprecated.Decimal,
	6:  deprecated.Date,
	7:  deprecated.TimeMillis,
	8:  deprecated.TimeMicros,
	9:  deprecated.TimestampMillis,
	10: deprecated.TimestampMicros,
	11: deprecated.Uint8,
	12: deprecated.Uint16,
	13: deprecated.Uint32,
	14: deprecated.Uint64,
	15: deprecated.Int8,
	16: deprecated.Int16,
	17: deprecated.Int32,
	18: deprecated.Int64,
	19: deprecated.Json,
	20: deprecated.Bson,
	21: deprecated.Interval,
}

type booleanType struct{}

func ( booleanType) () string                           { return "BOOLEAN" }
func ( booleanType) () Kind                               { return Boolean }
func ( booleanType) () int                              { return 1 }
func ( booleanType) ( int) int                   { return ( + 7) / 8 }
func ( booleanType) ( int) int              { return 8 *  }
func ( booleanType) (,  Value) int                   { return compareBool(.boolean(), .boolean()) }
func ( booleanType) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( booleanType) () *format.LogicalType         { return nil }
func ( booleanType) () *deprecated.ConvertedType { return nil }
func ( booleanType) () *format.Type               { return &physicalTypes[Boolean] }

func ( booleanType) ( int) ColumnIndexer {
	return newBooleanColumnIndexer()
}

func ( booleanType) (,  int) ColumnBuffer {
	return newBooleanColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( booleanType) (,  int,  encoding.Values) Dictionary {
	return newBooleanDictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( booleanType) (,  int,  encoding.Values) Page {
	return newBooleanPage(, makeColumnIndex(), makeNumValues(), )
}

func ( booleanType) ( []byte,  []uint32) encoding.Values {
	return encoding.BooleanValues()
}

func ( booleanType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeBoolean(, , )
}

func ( booleanType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeBoolean(, , )
}

func ( booleanType) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( booleanType) ( reflect.Value,  Value) error {
	 := .boolean()
	switch .Kind() {
	case reflect.Bool:
		.SetBool()
	default:
		.Set(reflect.ValueOf())
	}
	return nil
}

func ( booleanType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToBoolean()
	}
	switch .Kind() {
	case Boolean:
		return , nil
	case Int32:
		return convertInt32ToBoolean()
	case Int64:
		return convertInt64ToBoolean()
	case Int96:
		return convertInt96ToBoolean()
	case Float:
		return convertFloatToBoolean()
	case Double:
		return convertDoubleToBoolean()
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToBoolean()
	default:
		return makeValueKind(Boolean), nil
	}
}

type int32Type struct{}

func ( int32Type) () string                           { return "INT32" }
func ( int32Type) () Kind                               { return Int32 }
func ( int32Type) () int                              { return 32 }
func ( int32Type) ( int) int                   { return 4 *  }
func ( int32Type) ( int) int              { return  / 4 }
func ( int32Type) (,  Value) int                   { return compareInt32(.int32(), .int32()) }
func ( int32Type) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( int32Type) () *format.LogicalType         { return nil }
func ( int32Type) () *deprecated.ConvertedType { return nil }
func ( int32Type) () *format.Type               { return &physicalTypes[Int32] }

func ( int32Type) ( int) ColumnIndexer {
	return newInt32ColumnIndexer()
}

func ( int32Type) (,  int) ColumnBuffer {
	return newInt32ColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( int32Type) (,  int,  encoding.Values) Dictionary {
	return newInt32Dictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( int32Type) (,  int,  encoding.Values) Page {
	return newInt32Page(, makeColumnIndex(), makeNumValues(), )
}

func ( int32Type) ( []byte,  []uint32) encoding.Values {
	return encoding.Int32ValuesFromBytes()
}

func ( int32Type) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeInt32(, , )
}

func ( int32Type) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeInt32(, , )
}

func ( int32Type) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( int32Type) ( reflect.Value,  Value) error {
	 := .int32()
	switch .Kind() {
	case reflect.Int8, reflect.Int16, reflect.Int32:
		.SetInt(int64())
	case reflect.Uint8, reflect.Uint16, reflect.Uint32:
		.SetUint(uint64())
	default:
		.Set(reflect.ValueOf())
	}
	return nil
}

func ( int32Type) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToInt32()
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToInt32()
	case Int32:
		return , nil
	case Int64:
		return convertInt64ToInt32()
	case Int96:
		return convertInt96ToInt32()
	case Float:
		return convertFloatToInt32()
	case Double:
		return convertDoubleToInt32()
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToInt32()
	default:
		return makeValueKind(Int32), nil
	}
}

type int64Type struct{}

func ( int64Type) () string                           { return "INT64" }
func ( int64Type) () Kind                               { return Int64 }
func ( int64Type) () int                              { return 64 }
func ( int64Type) ( int) int                   { return 8 *  }
func ( int64Type) ( int) int              { return  / 8 }
func ( int64Type) (,  Value) int                   { return compareInt64(.int64(), .int64()) }
func ( int64Type) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( int64Type) () *format.LogicalType         { return nil }
func ( int64Type) () *deprecated.ConvertedType { return nil }
func ( int64Type) () *format.Type               { return &physicalTypes[Int64] }

func ( int64Type) ( int) ColumnIndexer {
	return newInt64ColumnIndexer()
}

func ( int64Type) (,  int) ColumnBuffer {
	return newInt64ColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( int64Type) (,  int,  encoding.Values) Dictionary {
	return newInt64Dictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( int64Type) (,  int,  encoding.Values) Page {
	return newInt64Page(, makeColumnIndex(), makeNumValues(), )
}

func ( int64Type) ( []byte,  []uint32) encoding.Values {
	return encoding.Int64ValuesFromBytes()
}

func ( int64Type) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeInt64(, , )
}

func ( int64Type) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeInt64(, , )
}

func ( int64Type) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( int64Type) ( reflect.Value,  Value) error {
	 := .int64()
	switch .Kind() {
	case reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, reflect.Int:
		.SetInt()
	case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uint, reflect.Uintptr:
		.SetUint(uint64())
	default:
		.Set(reflect.ValueOf())
	}
	return nil
}

func ( int64Type) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToInt64()
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToInt64()
	case Int32:
		return convertInt32ToInt64()
	case Int64:
		return , nil
	case Int96:
		return convertInt96ToInt64()
	case Float:
		return convertFloatToInt64()
	case Double:
		return convertDoubleToInt64()
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToInt64()
	default:
		return makeValueKind(Int64), nil
	}
}

type int96Type struct{}

func ( int96Type) () string { return "INT96" }

func ( int96Type) () Kind                               { return Int96 }
func ( int96Type) () int                              { return 96 }
func ( int96Type) ( int) int                   { return 12 *  }
func ( int96Type) ( int) int              { return  / 12 }
func ( int96Type) (,  Value) int                   { return compareInt96(.int96(), .int96()) }
func ( int96Type) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( int96Type) () *format.LogicalType         { return nil }
func ( int96Type) () *deprecated.ConvertedType { return nil }
func ( int96Type) () *format.Type               { return &physicalTypes[Int96] }

func ( int96Type) ( int) ColumnIndexer {
	return newInt96ColumnIndexer()
}

func ( int96Type) (,  int) ColumnBuffer {
	return newInt96ColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( int96Type) (,  int,  encoding.Values) Dictionary {
	return newInt96Dictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( int96Type) (,  int,  encoding.Values) Page {
	return newInt96Page(, makeColumnIndex(), makeNumValues(), )
}

func ( int96Type) ( []byte,  []uint32) encoding.Values {
	return encoding.Int96ValuesFromBytes()
}

func ( int96Type) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeInt96(, , )
}

func ( int96Type) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeInt96(, , )
}

func ( int96Type) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( int96Type) ( reflect.Value,  Value) error {
	 := .Int96()
	.Set(reflect.ValueOf())
	return nil
}

func ( int96Type) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToInt96()
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToInt96()
	case Int32:
		return convertInt32ToInt96()
	case Int64:
		return convertInt64ToInt96()
	case Int96:
		return , nil
	case Float:
		return convertFloatToInt96()
	case Double:
		return convertDoubleToInt96()
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToInt96()
	default:
		return makeValueKind(Int96), nil
	}
}

type floatType struct{}

func ( floatType) () string                           { return "FLOAT" }
func ( floatType) () Kind                               { return Float }
func ( floatType) () int                              { return 32 }
func ( floatType) ( int) int                   { return 4 *  }
func ( floatType) ( int) int              { return  / 4 }
func ( floatType) (,  Value) int                   { return compareFloat32(.float(), .float()) }
func ( floatType) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( floatType) () *format.LogicalType         { return nil }
func ( floatType) () *deprecated.ConvertedType { return nil }
func ( floatType) () *format.Type               { return &physicalTypes[Float] }

func ( floatType) ( int) ColumnIndexer {
	return newFloatColumnIndexer()
}

func ( floatType) (,  int) ColumnBuffer {
	return newFloatColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( floatType) (,  int,  encoding.Values) Dictionary {
	return newFloatDictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( floatType) (,  int,  encoding.Values) Page {
	return newFloatPage(, makeColumnIndex(), makeNumValues(), )
}

func ( floatType) ( []byte,  []uint32) encoding.Values {
	return encoding.FloatValuesFromBytes()
}

func ( floatType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeFloat(, , )
}

func ( floatType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeFloat(, , )
}

func ( floatType) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( floatType) ( reflect.Value,  Value) error {
	 := .float()
	switch .Kind() {
	case reflect.Float32, reflect.Float64:
		.SetFloat(float64())
	default:
		.Set(reflect.ValueOf())
	}
	return nil
}

func ( floatType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToFloat()
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToFloat()
	case Int32:
		return convertInt32ToFloat()
	case Int64:
		return convertInt64ToFloat()
	case Int96:
		return convertInt96ToFloat()
	case Float:
		return , nil
	case Double:
		return convertDoubleToFloat()
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToFloat()
	default:
		return makeValueKind(Float), nil
	}
}

type doubleType struct{}

func ( doubleType) () string                           { return "DOUBLE" }
func ( doubleType) () Kind                               { return Double }
func ( doubleType) () int                              { return 64 }
func ( doubleType) ( int) int                   { return 8 *  }
func ( doubleType) ( int) int              { return  / 8 }
func ( doubleType) (,  Value) int                   { return compareFloat64(.double(), .double()) }
func ( doubleType) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( doubleType) () *format.LogicalType         { return nil }
func ( doubleType) () *deprecated.ConvertedType { return nil }
func ( doubleType) () *format.Type               { return &physicalTypes[Double] }

func ( doubleType) ( int) ColumnIndexer {
	return newDoubleColumnIndexer()
}

func ( doubleType) (,  int) ColumnBuffer {
	return newDoubleColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( doubleType) (,  int,  encoding.Values) Dictionary {
	return newDoubleDictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( doubleType) (,  int,  encoding.Values) Page {
	return newDoublePage(, makeColumnIndex(), makeNumValues(), )
}

func ( doubleType) ( []byte,  []uint32) encoding.Values {
	return encoding.DoubleValuesFromBytes()
}

func ( doubleType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeDouble(, , )
}

func ( doubleType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeDouble(, , )
}

func ( doubleType) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( doubleType) ( reflect.Value,  Value) error {
	 := .double()
	switch .Kind() {
	case reflect.Float32, reflect.Float64:
		.SetFloat()
	default:
		.Set(reflect.ValueOf())
	}
	return nil
}

func ( doubleType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToDouble()
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToDouble()
	case Int32:
		return convertInt32ToDouble()
	case Int64:
		return convertInt64ToDouble()
	case Int96:
		return convertInt96ToDouble()
	case Float:
		return convertFloatToDouble()
	case Double:
		return , nil
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToDouble()
	default:
		return makeValueKind(Double), nil
	}
}

type byteArrayType struct{}

func ( byteArrayType) () string                           { return "BYTE_ARRAY" }
func ( byteArrayType) () Kind                               { return ByteArray }
func ( byteArrayType) () int                              { return 0 }
func ( byteArrayType) ( int) int                   { return estimatedSizeOfByteArrayValues *  }
func ( byteArrayType) ( int) int              { return  / estimatedSizeOfByteArrayValues }
func ( byteArrayType) (,  Value) int                   { return bytes.Compare(.byteArray(), .byteArray()) }
func ( byteArrayType) () *format.ColumnOrder         { return &typeDefinedColumnOrder }
func ( byteArrayType) () *format.LogicalType         { return nil }
func ( byteArrayType) () *deprecated.ConvertedType { return nil }
func ( byteArrayType) () *format.Type               { return &physicalTypes[ByteArray] }

func ( byteArrayType) ( int) ColumnIndexer {
	return newByteArrayColumnIndexer()
}

func ( byteArrayType) (,  int) ColumnBuffer {
	return newByteArrayColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( byteArrayType) (,  int,  encoding.Values) Dictionary {
	return newByteArrayDictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( byteArrayType) (,  int,  encoding.Values) Page {
	return newByteArrayPage(, makeColumnIndex(), makeNumValues(), )
}

func ( byteArrayType) ( []byte,  []uint32) encoding.Values {
	return encoding.ByteArrayValues(, )
}

func ( byteArrayType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeByteArray(, , )
}

func ( byteArrayType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeByteArray(, , )
}

func ( byteArrayType) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateDecodeByteArraySize()
}

func ( byteArrayType) ( reflect.Value,  Value) error {
	 := .byteArray()
	switch .Kind() {
	case reflect.String:
		.SetString(string())
	case reflect.Slice:
		.SetBytes(copyBytes())
	default:
		 := reflect.ValueOf(string())
		.Set()
	}
	return nil
}

func ( byteArrayType) ( Value,  Type) (Value, error) {
	switch .Kind() {
	case Boolean:
		return convertBooleanToByteArray()
	case Int32:
		return convertInt32ToByteArray()
	case Int64:
		return convertInt64ToByteArray()
	case Int96:
		return convertInt96ToByteArray()
	case Float:
		return convertFloatToByteArray()
	case Double:
		return convertDoubleToByteArray()
	case ByteArray, FixedLenByteArray:
		return , nil
	default:
		return makeValueKind(ByteArray), nil
	}
}

type fixedLenByteArrayType struct{ length int }

func ( fixedLenByteArrayType) () string {
	return fmt.Sprintf("FIXED_LEN_BYTE_ARRAY(%d)", .length)
}

func ( fixedLenByteArrayType) () Kind { return FixedLenByteArray }

func ( fixedLenByteArrayType) () int { return .length }

func ( fixedLenByteArrayType) ( int) int { return .length *  }

func ( fixedLenByteArrayType) ( int) int { return  / .length }

func ( fixedLenByteArrayType) (,  Value) int {
	return bytes.Compare(.byteArray(), .byteArray())
}

func ( fixedLenByteArrayType) () *format.ColumnOrder { return &typeDefinedColumnOrder }

func ( fixedLenByteArrayType) () *format.LogicalType { return nil }

func ( fixedLenByteArrayType) () *deprecated.ConvertedType { return nil }

func ( fixedLenByteArrayType) () *format.Type { return &physicalTypes[FixedLenByteArray] }

func ( fixedLenByteArrayType) ( int) ColumnIndexer {
	return newFixedLenByteArrayColumnIndexer(.length, )
}

func ( fixedLenByteArrayType) (,  int) ColumnBuffer {
	return newFixedLenByteArrayColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( fixedLenByteArrayType) (,  int,  encoding.Values) Dictionary {
	return newFixedLenByteArrayDictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( fixedLenByteArrayType) (,  int,  encoding.Values) Page {
	return newFixedLenByteArrayPage(, makeColumnIndex(), makeNumValues(), )
}

func ( fixedLenByteArrayType) ( []byte,  []uint32) encoding.Values {
	return encoding.FixedLenByteArrayValues(, .length)
}

func ( fixedLenByteArrayType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeFixedLenByteArray(, , )
}

func ( fixedLenByteArrayType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeFixedLenByteArray(, , )
}

func ( fixedLenByteArrayType) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( fixedLenByteArrayType) ( reflect.Value,  Value) error {
	 := .byteArray()
	switch .Kind() {
	case reflect.Array:
		if .Type().Elem().Kind() == reflect.Uint8 && .Len() == len() {
			// This code could be implemented as a call to reflect.Copy but
			// it would require creating a reflect.Value from v which causes
			// the heap allocation to pack the []byte value. To avoid this
			// overhead we instead convert the reflect.Value holding the
			// destination array into a byte slice which allows us to use
			// a more efficient call to copy.
			 := unsafe.Slice((*byte)(reflectValueData()), len())
			copy(, )
			return nil
		}
	case reflect.Slice:
		.SetBytes(copyBytes())
		return nil
	}

	 := reflect.ValueOf(copyBytes())
	.Set()
	return nil
}

func reflectValueData( reflect.Value) unsafe.Pointer {
	return (*[2]unsafe.Pointer)(unsafe.Pointer(&))[1]
}

func ( fixedLenByteArrayType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *stringType:
		return convertStringToFixedLenByteArray(, .length)
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToFixedLenByteArray(, .length)
	case Int32:
		return convertInt32ToFixedLenByteArray(, .length)
	case Int64:
		return convertInt64ToFixedLenByteArray(, .length)
	case Int96:
		return convertInt96ToFixedLenByteArray(, .length)
	case Float:
		return convertFloatToFixedLenByteArray(, .length)
	case Double:
		return convertDoubleToFixedLenByteArray(, .length)
	case ByteArray, FixedLenByteArray:
		return convertByteArrayToFixedLenByteArray(, .length)
	default:
		return makeValueBytes(FixedLenByteArray, make([]byte, .length)), nil
	}
}

type uint32Type struct{ int32Type }

func ( uint32Type) (,  Value) int {
	return compareUint32(.uint32(), .uint32())
}

func ( uint32Type) ( int) ColumnIndexer {
	return newUint32ColumnIndexer()
}

func ( uint32Type) (,  int) ColumnBuffer {
	return newUint32ColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( uint32Type) (,  int,  encoding.Values) Dictionary {
	return newUint32Dictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( uint32Type) (,  int,  encoding.Values) Page {
	return newUint32Page(, makeColumnIndex(), makeNumValues(), )
}

type uint64Type struct{ int64Type }

func ( uint64Type) (,  Value) int {
	return compareUint64(.uint64(), .uint64())
}

func ( uint64Type) ( int) ColumnIndexer {
	return newUint64ColumnIndexer()
}

func ( uint64Type) (,  int) ColumnBuffer {
	return newUint64ColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( uint64Type) (,  int,  encoding.Values) Dictionary {
	return newUint64Dictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( uint64Type) (,  int,  encoding.Values) Page {
	return newUint64Page(, makeColumnIndex(), makeNumValues(), )
}

// BE128 stands for "big-endian 128 bits". This type is used as a special case
// for fixed-length byte arrays of 16 bytes, which are commonly used to
// represent columns of random unique identifiers such as UUIDs.
//
// Comparisons of BE128 values use the natural byte order, the zeroth byte is
// the most significant byte.
//
// The special case is intended to provide optimizations based on the knowledge
// that the values are 16 bytes long. Stronger type checking can also be applied
// by the compiler when using [16]byte values rather than []byte, reducing the
// risk of errors on these common code paths.
type be128Type struct{}

func ( be128Type) () string { return "FIXED_LEN_BYTE_ARRAY(16)" }

func ( be128Type) () Kind { return FixedLenByteArray }

func ( be128Type) () int { return 16 }

func ( be128Type) ( int) int { return 16 *  }

func ( be128Type) ( int) int { return  / 16 }

func ( be128Type) (,  Value) int { return compareBE128(.be128(), .be128()) }

func ( be128Type) () *format.ColumnOrder { return &typeDefinedColumnOrder }

func ( be128Type) () *format.LogicalType { return nil }

func ( be128Type) () *deprecated.ConvertedType { return nil }

func ( be128Type) () *format.Type { return &physicalTypes[FixedLenByteArray] }

func ( be128Type) ( int) ColumnIndexer {
	return newBE128ColumnIndexer()
}

func ( be128Type) (,  int) ColumnBuffer {
	return newBE128ColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( be128Type) (,  int,  encoding.Values) Dictionary {
	return newBE128Dictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( be128Type) (,  int,  encoding.Values) Page {
	return newBE128Page(, makeColumnIndex(), makeNumValues(), )
}

func ( be128Type) ( []byte,  []uint32) encoding.Values {
	return encoding.FixedLenByteArrayValues(, 16)
}

func ( be128Type) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeFixedLenByteArray(, , )
}

func ( be128Type) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeFixedLenByteArray(, , )
}

func ( be128Type) ( int,  []byte,  encoding.Encoding) int {
	return .EstimateSize()
}

func ( be128Type) ( reflect.Value,  Value) error {
	return fixedLenByteArrayType{length: 16}.AssignValue(, )
}

func ( be128Type) ( Value,  Type) (Value, error) {
	return fixedLenByteArrayType{length: 16}.ConvertValue(, )
}

// FixedLenByteArrayType constructs a type for fixed-length values of the given
// size (in bytes).
func ( int) Type {
	switch  {
	case 16:
		return be128Type{}
	default:
		return fixedLenByteArrayType{length: }
	}
}

// Int constructs a leaf node of signed integer logical type of the given bit
// width.
//
// The bit width must be one of 8, 16, 32, 64, or the function will panic.
func ( int) Node {
	return Leaf(integerType(, &signedIntTypes))
}

// Uint constructs a leaf node of unsigned integer logical type of the given
// bit width.
//
// The bit width must be one of 8, 16, 32, 64, or the function will panic.
func ( int) Node {
	return Leaf(integerType(, &unsignedIntTypes))
}

func integerType( int,  *[4]intType) *intType {
	switch  {
	case 8:
		return &[0]
	case 16:
		return &[1]
	case 32:
		return &[2]
	case 64:
		return &[3]
	default:
		panic(fmt.Sprintf("cannot create a %d bits parquet integer node", ))
	}
}

var signedIntTypes = [...]intType{
	{BitWidth: 8, IsSigned: true},
	{BitWidth: 16, IsSigned: true},
	{BitWidth: 32, IsSigned: true},
	{BitWidth: 64, IsSigned: true},
}

var unsignedIntTypes = [...]intType{
	{BitWidth: 8, IsSigned: false},
	{BitWidth: 16, IsSigned: false},
	{BitWidth: 32, IsSigned: false},
	{BitWidth: 64, IsSigned: false},
}

type intType format.IntType

func ( *intType) () Type {
	if .IsSigned {
		if .BitWidth == 64 {
			return int64Type{}
		} else {
			return int32Type{}
		}
	} else {
		if .BitWidth == 64 {
			return uint64Type{}
		} else {
			return uint32Type{}
		}
	}
}

func ( *intType) () string { return (*format.IntType)().String() }

func ( *intType) () Kind { return .baseType().Kind() }

func ( *intType) () int { return int(.BitWidth) }

func ( *intType) ( int) int { return (int(.BitWidth) / 8) *  }

func ( *intType) ( int) int { return  / (int(.BitWidth) / 8) }

func ( *intType) (,  Value) int {
	// This code is similar to t.baseType().Compare(a,b) but comparison methods
	// tend to be invoked a lot (e.g. when sorting) so avoiding the interface
	// indirection in this case yields much better throughput in some cases.
	if .BitWidth == 64 {
		 := .int64()
		 := .int64()
		if .IsSigned {
			return compareInt64(, )
		} else {
			return compareUint64(uint64(), uint64())
		}
	} else {
		 := .int32()
		 := .int32()
		if .IsSigned {
			return compareInt32(, )
		} else {
			return compareUint32(uint32(), uint32())
		}
	}
}

func ( *intType) () *format.ColumnOrder { return .baseType().ColumnOrder() }

func ( *intType) () *format.Type { return .baseType().PhysicalType() }

func ( *intType) () *format.LogicalType {
	return &format.LogicalType{Integer: (*format.IntType)()}
}

func ( *intType) () *deprecated.ConvertedType {
	 := bits.Len8(uint8(.BitWidth)/8) - 1 // 8=>0, 16=>1, 32=>2, 64=>4
	if .IsSigned {
		 += int(deprecated.Int8)
	} else {
		 += int(deprecated.Uint8)
	}
	return &convertedTypes[]
}

func ( *intType) ( int) ColumnIndexer {
	return .baseType().NewColumnIndexer()
}

func ( *intType) (,  int) ColumnBuffer {
	return .baseType().NewColumnBuffer(, )
}

func ( *intType) (,  int,  encoding.Values) Dictionary {
	return .baseType().NewDictionary(, , )
}

func ( *intType) (,  int,  encoding.Values) Page {
	return .baseType().NewPage(, , )
}

func ( *intType) ( []byte,  []uint32) encoding.Values {
	return .baseType().NewValues(, )
}

func ( *intType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return .baseType().Encode(, , )
}

func ( *intType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return .baseType().Decode(, , )
}

func ( *intType) ( int,  []byte,  encoding.Encoding) int {
	return .baseType().EstimateDecodeSize(, , )
}

func ( *intType) ( reflect.Value,  Value) error {
	if .BitWidth == 64 {
		return int64Type{}.AssignValue(, )
	} else {
		return int32Type{}.AssignValue(, )
	}
}

func ( *intType) ( Value,  Type) (Value, error) {
	if .BitWidth == 64 {
		return int64Type{}.ConvertValue(, )
	} else {
		return int32Type{}.ConvertValue(, )
	}
}

// Decimal constructs a leaf node of decimal logical type with the given
// scale, precision, and underlying type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#decimal
func (,  int,  Type) Node {
	switch .Kind() {
	case Int32, Int64, FixedLenByteArray:
	default:
		panic("DECIMAL node must annotate Int32, Int64 or FixedLenByteArray but got " + .String())
	}
	return Leaf(&decimalType{
		decimal: format.DecimalType{
			Scale:     int32(),
			Precision: int32(),
		},
		Type: ,
	})
}

type decimalType struct {
	decimal format.DecimalType
	Type
}

func ( *decimalType) () string { return .decimal.String() }

func ( *decimalType) () *format.LogicalType {
	return &format.LogicalType{Decimal: &.decimal}
}

func ( *decimalType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.Decimal]
}

// String constructs a leaf node of UTF8 logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#string
func () Node { return Leaf(&stringType{}) }

type stringType format.StringType

func ( *stringType) () string { return (*format.StringType)().String() }

func ( *stringType) () Kind { return ByteArray }

func ( *stringType) () int { return 0 }

func ( *stringType) ( int) int { return byteArrayType{}.EstimateSize() }

func ( *stringType) ( int) int { return byteArrayType{}.EstimateNumValues() }

func ( *stringType) (,  Value) int {
	return bytes.Compare(.byteArray(), .byteArray())
}

func ( *stringType) () *format.ColumnOrder {
	return &typeDefinedColumnOrder
}

func ( *stringType) () *format.Type {
	return &physicalTypes[ByteArray]
}

func ( *stringType) () *format.LogicalType {
	return &format.LogicalType{UTF8: (*format.StringType)()}
}

func ( *stringType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.UTF8]
}

func ( *stringType) ( int) ColumnIndexer {
	return newByteArrayColumnIndexer()
}

func ( *stringType) (,  int,  encoding.Values) Dictionary {
	return newByteArrayDictionary(, makeColumnIndex(), makeNumValues(), )
}

func ( *stringType) (,  int) ColumnBuffer {
	return newByteArrayColumnBuffer(, makeColumnIndex(), makeNumValues())
}

func ( *stringType) (,  int,  encoding.Values) Page {
	return newByteArrayPage(, makeColumnIndex(), makeNumValues(), )
}

func ( *stringType) ( []byte,  []uint32) encoding.Values {
	return encoding.ByteArrayValues(, )
}

func ( *stringType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return encoding.EncodeByteArray(, , )
}

func ( *stringType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return encoding.DecodeByteArray(, , )
}

func ( *stringType) ( int,  []byte,  encoding.Encoding) int {
	return byteArrayType{}.EstimateDecodeSize(, , )
}

func ( *stringType) ( reflect.Value,  Value) error {
	return byteArrayType{}.AssignValue(, )
}

func ( *stringType) ( Value,  Type) (Value, error) {
	switch t2 := .(type) {
	case *dateType:
		return convertDateToString()
	case *timeType:
		 := .tz()
		if .Unit.Micros != nil {
			return convertTimeMicrosToString(, )
		} else {
			return convertTimeMillisToString(, )
		}
	}
	switch .Kind() {
	case Boolean:
		return convertBooleanToString()
	case Int32:
		return convertInt32ToString()
	case Int64:
		return convertInt64ToString()
	case Int96:
		return convertInt96ToString()
	case Float:
		return convertFloatToString()
	case Double:
		return convertDoubleToString()
	case ByteArray:
		return , nil
	case FixedLenByteArray:
		return convertFixedLenByteArrayToString()
	default:
		return makeValueKind(ByteArray), nil
	}
}

// UUID constructs a leaf node of UUID logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#uuid
func () Node { return Leaf(&uuidType{}) }

type uuidType format.UUIDType

func ( *uuidType) () string { return (*format.UUIDType)().String() }

func ( *uuidType) () Kind { return be128Type{}.Kind() }

func ( *uuidType) () int { return be128Type{}.Length() }

func ( *uuidType) ( int) int { return be128Type{}.EstimateSize() }

func ( *uuidType) ( int) int { return be128Type{}.EstimateNumValues() }

func ( *uuidType) (,  Value) int { return be128Type{}.Compare(, ) }

func ( *uuidType) () *format.ColumnOrder { return &typeDefinedColumnOrder }

func ( *uuidType) () *format.Type { return &physicalTypes[FixedLenByteArray] }

func ( *uuidType) () *format.LogicalType {
	return &format.LogicalType{UUID: (*format.UUIDType)()}
}

func ( *uuidType) () *deprecated.ConvertedType { return nil }

func ( *uuidType) ( int) ColumnIndexer {
	return be128Type{}.NewColumnIndexer()
}

func ( *uuidType) (,  int,  encoding.Values) Dictionary {
	return be128Type{}.NewDictionary(, , )
}

func ( *uuidType) (,  int) ColumnBuffer {
	return be128Type{}.NewColumnBuffer(, )
}

func ( *uuidType) (,  int,  encoding.Values) Page {
	return be128Type{}.NewPage(, , )
}

func ( *uuidType) ( []byte,  []uint32) encoding.Values {
	return be128Type{}.NewValues(, )
}

func ( *uuidType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return be128Type{}.Encode(, , )
}

func ( *uuidType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return be128Type{}.Decode(, , )
}

func ( *uuidType) ( int,  []byte,  encoding.Encoding) int {
	return be128Type{}.EstimateDecodeSize(, , )
}

func ( *uuidType) ( reflect.Value,  Value) error {
	return be128Type{}.AssignValue(, )
}

func ( *uuidType) ( Value,  Type) (Value, error) {
	return be128Type{}.ConvertValue(, )
}

// Enum constructs a leaf node with a logical type representing enumerations.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#enum
func () Node { return Leaf(&enumType{}) }

type enumType format.EnumType

func ( *enumType) () string { return (*format.EnumType)().String() }

func ( *enumType) () Kind { return new(stringType).Kind() }

func ( *enumType) () int { return new(stringType).Length() }

func ( *enumType) ( int) int { return new(stringType).EstimateSize() }

func ( *enumType) ( int) int { return new(stringType).EstimateNumValues() }

func ( *enumType) (,  Value) int { return new(stringType).Compare(, ) }

func ( *enumType) () *format.ColumnOrder { return new(stringType).ColumnOrder() }

func ( *enumType) () *format.Type { return new(stringType).PhysicalType() }

func ( *enumType) () *format.LogicalType {
	return &format.LogicalType{Enum: (*format.EnumType)()}
}

func ( *enumType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.Enum]
}

func ( *enumType) ( int) ColumnIndexer {
	return new(stringType).NewColumnIndexer()
}

func ( *enumType) (,  int,  encoding.Values) Dictionary {
	return new(stringType).NewDictionary(, , )
}

func ( *enumType) (,  int) ColumnBuffer {
	return new(stringType).NewColumnBuffer(, )
}

func ( *enumType) (,  int,  encoding.Values) Page {
	return new(stringType).NewPage(, , )
}

func ( *enumType) ( []byte,  []uint32) encoding.Values {
	return new(stringType).NewValues(, )
}

func ( *enumType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return new(stringType).Encode(, , )
}

func ( *enumType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return new(stringType).Decode(, , )
}

func ( *enumType) ( int,  []byte,  encoding.Encoding) int {
	return new(stringType).EstimateDecodeSize(, , )
}

func ( *enumType) ( reflect.Value,  Value) error {
	return new(stringType).AssignValue(, )
}

func ( *enumType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *byteArrayType, *stringType, *enumType:
		return , nil
	default:
		return , invalidConversion(, "ENUM", .String())
	}
}

// JSON constructs a leaf node of JSON logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#json
func () Node { return Leaf(&jsonType{}) }

type jsonType format.JsonType

func ( *jsonType) () string { return (*format.JsonType)().String() }

func ( *jsonType) () Kind { return byteArrayType{}.Kind() }

func ( *jsonType) () int { return byteArrayType{}.Length() }

func ( *jsonType) ( int) int { return byteArrayType{}.EstimateSize() }

func ( *jsonType) ( int) int { return byteArrayType{}.EstimateNumValues() }

func ( *jsonType) (,  Value) int { return byteArrayType{}.Compare(, ) }

func ( *jsonType) () *format.ColumnOrder { return byteArrayType{}.ColumnOrder() }

func ( *jsonType) () *format.Type { return byteArrayType{}.PhysicalType() }

func ( *jsonType) () *format.LogicalType {
	return &format.LogicalType{Json: (*format.JsonType)()}
}

func ( *jsonType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.Json]
}

func ( *jsonType) ( int) ColumnIndexer {
	return byteArrayType{}.NewColumnIndexer()
}

func ( *jsonType) (,  int,  encoding.Values) Dictionary {
	return byteArrayType{}.NewDictionary(, , )
}

func ( *jsonType) (,  int) ColumnBuffer {
	return byteArrayType{}.NewColumnBuffer(, )
}

func ( *jsonType) (,  int,  encoding.Values) Page {
	return byteArrayType{}.NewPage(, , )
}

func ( *jsonType) ( []byte,  []uint32) encoding.Values {
	return byteArrayType{}.NewValues(, )
}

func ( *jsonType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return byteArrayType{}.Encode(, , )
}

func ( *jsonType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return byteArrayType{}.Decode(, , )
}

func ( *jsonType) ( int,  []byte,  encoding.Encoding) int {
	return byteArrayType{}.EstimateDecodeSize(, , )
}

func ( *jsonType) ( reflect.Value,  Value) error {
	// Assign value using ByteArrayType for BC...
	switch .Kind() {
	case reflect.String:
		return byteArrayType{}.AssignValue(, )
	case reflect.Slice:
		if .Type().Elem().Kind() == reflect.Uint8 {
			return byteArrayType{}.AssignValue(, )
		}
	}

	// Otherwise handle with json.Unmarshal
	 := .byteArray()
	 := reflect.New(.Type()).Elem()
	 := json.Unmarshal(, .Addr().Interface())
	if  != nil {
		return 
	}
	.Set()
	return nil
}

func ( *jsonType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *byteArrayType, *stringType, *jsonType:
		return , nil
	default:
		return , invalidConversion(, "JSON", .String())
	}
}

// BSON constructs a leaf node of BSON logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#bson
func () Node { return Leaf(&bsonType{}) }

type bsonType format.BsonType

func ( *bsonType) () string { return (*format.BsonType)().String() }

func ( *bsonType) () Kind { return byteArrayType{}.Kind() }

func ( *bsonType) () int { return byteArrayType{}.Length() }

func ( *bsonType) ( int) int { return byteArrayType{}.EstimateSize() }

func ( *bsonType) ( int) int { return byteArrayType{}.EstimateNumValues() }

func ( *bsonType) (,  Value) int { return byteArrayType{}.Compare(, ) }

func ( *bsonType) () *format.ColumnOrder { return byteArrayType{}.ColumnOrder() }

func ( *bsonType) () *format.Type { return byteArrayType{}.PhysicalType() }

func ( *bsonType) () *format.LogicalType {
	return &format.LogicalType{Bson: (*format.BsonType)()}
}

func ( *bsonType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.Bson]
}

func ( *bsonType) ( int) ColumnIndexer {
	return byteArrayType{}.NewColumnIndexer()
}

func ( *bsonType) (,  int,  encoding.Values) Dictionary {
	return byteArrayType{}.NewDictionary(, , )
}

func ( *bsonType) (,  int) ColumnBuffer {
	return byteArrayType{}.NewColumnBuffer(, )
}

func ( *bsonType) (,  int,  encoding.Values) Page {
	return byteArrayType{}.NewPage(, , )
}

func ( *bsonType) ( []byte,  []uint32) encoding.Values {
	return byteArrayType{}.NewValues(, )
}

func ( *bsonType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return byteArrayType{}.Encode(, , )
}

func ( *bsonType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return byteArrayType{}.Decode(, , )
}

func ( *bsonType) ( int,  []byte,  encoding.Encoding) int {
	return byteArrayType{}.EstimateDecodeSize(, , )
}

func ( *bsonType) ( reflect.Value,  Value) error {
	return byteArrayType{}.AssignValue(, )
}

func ( *bsonType) ( Value,  Type) (Value, error) {
	switch .(type) {
	case *byteArrayType, *bsonType:
		return , nil
	default:
		return , invalidConversion(, "BSON", .String())
	}
}

// Date constructs a leaf node of DATE logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#date
func () Node { return Leaf(&dateType{}) }

type dateType format.DateType

func ( *dateType) () string { return (*format.DateType)().String() }

func ( *dateType) () Kind { return int32Type{}.Kind() }

func ( *dateType) () int { return int32Type{}.Length() }

func ( *dateType) ( int) int { return int32Type{}.EstimateSize() }

func ( *dateType) ( int) int { return int32Type{}.EstimateNumValues() }

func ( *dateType) (,  Value) int { return int32Type{}.Compare(, ) }

func ( *dateType) () *format.ColumnOrder { return int32Type{}.ColumnOrder() }

func ( *dateType) () *format.Type { return int32Type{}.PhysicalType() }

func ( *dateType) () *format.LogicalType {
	return &format.LogicalType{Date: (*format.DateType)()}
}

func ( *dateType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.Date]
}

func ( *dateType) ( int) ColumnIndexer {
	return int32Type{}.NewColumnIndexer()
}

func ( *dateType) (,  int,  encoding.Values) Dictionary {
	return int32Type{}.NewDictionary(, , )
}

func ( *dateType) (,  int) ColumnBuffer {
	return int32Type{}.NewColumnBuffer(, )
}

func ( *dateType) (,  int,  encoding.Values) Page {
	return int32Type{}.NewPage(, , )
}

func ( *dateType) ( []byte,  []uint32) encoding.Values {
	return int32Type{}.NewValues(, )
}

func ( *dateType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return int32Type{}.Encode(, , )
}

func ( *dateType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return int32Type{}.Decode(, , )
}

func ( *dateType) ( int,  []byte,  encoding.Encoding) int {
	return int32Type{}.EstimateDecodeSize(, , )
}

func ( *dateType) ( reflect.Value,  Value) error {
	return int32Type{}.AssignValue(, )
}

func ( *dateType) ( Value,  Type) (Value, error) {
	switch src := .(type) {
	case *stringType:
		return convertStringToDate(, time.UTC)
	case *timestampType:
		return convertTimestampToDate(, .Unit, .tz())
	}
	return int32Type{}.ConvertValue(, )
}

// TimeUnit represents units of time in the parquet type system.
type TimeUnit interface {
	// Returns the precision of the time unit as a time.Duration value.
	Duration() time.Duration
	// Converts the TimeUnit value to its representation in the parquet thrift
	// format.
	TimeUnit() format.TimeUnit
}

var (
	Millisecond TimeUnit = &millisecond{}
	Microsecond TimeUnit = &microsecond{}
	Nanosecond  TimeUnit = &nanosecond{}
)

type millisecond format.MilliSeconds

func ( *millisecond) () time.Duration { return time.Millisecond }
func ( *millisecond) () format.TimeUnit {
	return format.TimeUnit{Millis: (*format.MilliSeconds)()}
}

type microsecond format.MicroSeconds

func ( *microsecond) () time.Duration { return time.Microsecond }
func ( *microsecond) () format.TimeUnit {
	return format.TimeUnit{Micros: (*format.MicroSeconds)()}
}

type nanosecond format.NanoSeconds

func ( *nanosecond) () time.Duration { return time.Nanosecond }
func ( *nanosecond) () format.TimeUnit {
	return format.TimeUnit{Nanos: (*format.NanoSeconds)()}
}

// Time constructs a leaf node of TIME logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#time
func ( TimeUnit) Node {
	return Leaf(&timeType{IsAdjustedToUTC: true, Unit: .TimeUnit()})
}

type timeType format.TimeType

func ( *timeType) () *time.Location {
	if .IsAdjustedToUTC {
		return time.UTC
	} else {
		return time.Local
	}
}

func ( *timeType) () Type {
	if .useInt32() {
		return int32Type{}
	} else {
		return int64Type{}
	}
}

func ( *timeType) () bool { return .Unit.Millis != nil }

func ( *timeType) () bool { return .Unit.Micros != nil }

func ( *timeType) () string { return (*format.TimeType)().String() }

func ( *timeType) () Kind { return .baseType().Kind() }

func ( *timeType) () int { return .baseType().Length() }

func ( *timeType) ( int) int { return .baseType().EstimateSize() }

func ( *timeType) ( int) int { return .baseType().EstimateNumValues() }

func ( *timeType) (,  Value) int { return .baseType().Compare(, ) }

func ( *timeType) () *format.ColumnOrder { return .baseType().ColumnOrder() }

func ( *timeType) () *format.Type { return .baseType().PhysicalType() }

func ( *timeType) () *format.LogicalType {
	return &format.LogicalType{Time: (*format.TimeType)()}
}

func ( *timeType) () *deprecated.ConvertedType {
	switch {
	case .useInt32():
		return &convertedTypes[deprecated.TimeMillis]
	case .useInt64():
		return &convertedTypes[deprecated.TimeMicros]
	default:
		return nil
	}
}

func ( *timeType) ( int) ColumnIndexer {
	return .baseType().NewColumnIndexer()
}

func ( *timeType) (,  int) ColumnBuffer {
	return .baseType().NewColumnBuffer(, )
}

func ( *timeType) (,  int,  encoding.Values) Dictionary {
	return .baseType().NewDictionary(, , )
}

func ( *timeType) (,  int,  encoding.Values) Page {
	return .baseType().NewPage(, , )
}

func ( *timeType) ( []byte,  []uint32) encoding.Values {
	return .baseType().NewValues(, )
}

func ( *timeType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return .baseType().Encode(, , )
}

func ( *timeType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return .baseType().Decode(, , )
}

func ( *timeType) ( int,  []byte,  encoding.Encoding) int {
	return .baseType().EstimateDecodeSize(, , )
}

func ( *timeType) ( reflect.Value,  Value) error {
	return .baseType().AssignValue(, )
}

func ( *timeType) ( Value,  Type) (Value, error) {
	switch src := .(type) {
	case *stringType:
		 := .tz()
		if .Unit.Micros != nil {
			return convertStringToTimeMicros(, )
		} else {
			return convertStringToTimeMillis(, )
		}
	case *timestampType:
		 := .tz()
		if .Unit.Micros != nil {
			return convertTimestampToTimeMicros(, .Unit, .tz(), )
		} else {
			return convertTimestampToTimeMillis(, .Unit, .tz(), )
		}
	}
	return .baseType().ConvertValue(, )
}

// Timestamp constructs of leaf node of TIMESTAMP logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#timestamp
func ( TimeUnit) Node {
	return Leaf(&timestampType{IsAdjustedToUTC: true, Unit: .TimeUnit()})
}

type timestampType format.TimestampType

func ( *timestampType) () *time.Location {
	if .IsAdjustedToUTC {
		return time.UTC
	} else {
		return time.Local
	}
}

func ( *timestampType) () string { return (*format.TimestampType)().String() }

func ( *timestampType) () Kind { return int64Type{}.Kind() }

func ( *timestampType) () int { return int64Type{}.Length() }

func ( *timestampType) ( int) int { return int64Type{}.EstimateSize() }

func ( *timestampType) ( int) int { return int64Type{}.EstimateNumValues() }

func ( *timestampType) (,  Value) int { return int64Type{}.Compare(, ) }

func ( *timestampType) () *format.ColumnOrder { return int64Type{}.ColumnOrder() }

func ( *timestampType) () *format.Type { return int64Type{}.PhysicalType() }

func ( *timestampType) () *format.LogicalType {
	return &format.LogicalType{Timestamp: (*format.TimestampType)()}
}

func ( *timestampType) () *deprecated.ConvertedType {
	switch {
	case .Unit.Millis != nil:
		return &convertedTypes[deprecated.TimestampMillis]
	case .Unit.Micros != nil:
		return &convertedTypes[deprecated.TimestampMicros]
	default:
		return nil
	}
}

func ( *timestampType) ( int) ColumnIndexer {
	return int64Type{}.NewColumnIndexer()
}

func ( *timestampType) (,  int,  encoding.Values) Dictionary {
	return int64Type{}.NewDictionary(, , )
}

func ( *timestampType) (,  int) ColumnBuffer {
	return int64Type{}.NewColumnBuffer(, )
}

func ( *timestampType) (,  int,  encoding.Values) Page {
	return int64Type{}.NewPage(, , )
}

func ( *timestampType) ( []byte,  []uint32) encoding.Values {
	return int64Type{}.NewValues(, )
}

func ( *timestampType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return int64Type{}.Encode(, , )
}

func ( *timestampType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return int64Type{}.Decode(, , )
}

func ( *timestampType) ( int,  []byte,  encoding.Encoding) int {
	return int64Type{}.EstimateDecodeSize(, , )
}

func ( *timestampType) ( reflect.Value,  Value) error {
	switch .Type() {
	case reflect.TypeOf(time.Time{}):
		 := Nanosecond.TimeUnit()
		 := .LogicalType()
		if  != nil && .Timestamp != nil {
			 = .Timestamp.Unit
		}

		 := .int64()
		switch {
		case .Millis != nil:
			 =  * 1e6
		case .Micros != nil:
			 =  * 1e3
		}

		 := time.Unix(0, ).UTC()
		.Set(reflect.ValueOf())
		return nil
	default:
		return int64Type{}.AssignValue(, )
	}
}

func ( *timestampType) ( Value,  Type) (Value, error) {
	switch src := .(type) {
	case *timestampType:
		return convertTimestampToTimestamp(, .Unit, .Unit)
	case *dateType:
		return convertDateToTimestamp(, .Unit, .tz())
	}
	return int64Type{}.ConvertValue(, )
}

// List constructs a node of LIST logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#lists
func ( Node) Node {
	return listNode{Group{"list": Repeated(Group{"element": })}}
}

type listNode struct{ Group }

func (listNode) () Type { return &listType{} }

type listType format.ListType

func ( *listType) () string { return (*format.ListType)().String() }

func ( *listType) () Kind { panic("cannot call Kind on parquet LIST type") }

func ( *listType) () int { return 0 }

func ( *listType) (int) int { return 0 }

func ( *listType) (int) int { return 0 }

func ( *listType) (Value, Value) int { panic("cannot compare values on parquet LIST type") }

func ( *listType) () *format.ColumnOrder { return nil }

func ( *listType) () *format.Type { return nil }

func ( *listType) () *format.LogicalType {
	return &format.LogicalType{List: (*format.ListType)()}
}

func ( *listType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.List]
}

func ( *listType) (int) ColumnIndexer {
	panic("create create column indexer from parquet LIST type")
}

func ( *listType) (int, int, encoding.Values) Dictionary {
	panic("cannot create dictionary from parquet LIST type")
}

func ( *listType) (int, int) ColumnBuffer {
	panic("cannot create column buffer from parquet LIST type")
}

func ( *listType) (int, int, encoding.Values) Page {
	panic("cannot create page from parquet LIST type")
}

func ( *listType) ( []byte,  []uint32) encoding.Values {
	panic("cannot create values from parquet LIST type")
}

func ( *listType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	panic("cannot encode parquet LIST type")
}

func ( *listType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	panic("cannot decode parquet LIST type")
}

func ( *listType) ( int,  []byte,  encoding.Encoding) int {
	panic("cannot estimate decode size of parquet LIST type")
}

func ( *listType) (reflect.Value, Value) error {
	panic("cannot assign value to a parquet LIST type")
}

func ( *listType) (Value, Type) (Value, error) {
	panic("cannot convert value to a parquet LIST type")
}

// Map constructs a node of MAP logical type.
//
// https://github.com/apache/parquet-format/blob/master/LogicalTypes.md#maps
func (,  Node) Node {
	return mapNode{Group{
		"key_value": Repeated(Group{
			"key":   Required(),
			"value": ,
		}),
	}}
}

type mapNode struct{ Group }

func (mapNode) () Type { return &mapType{} }

type mapType format.MapType

func ( *mapType) () string { return (*format.MapType)().String() }

func ( *mapType) () Kind { panic("cannot call Kind on parquet MAP type") }

func ( *mapType) () int { return 0 }

func ( *mapType) (int) int { return 0 }

func ( *mapType) (int) int { return 0 }

func ( *mapType) (Value, Value) int { panic("cannot compare values on parquet MAP type") }

func ( *mapType) () *format.ColumnOrder { return nil }

func ( *mapType) () *format.Type { return nil }

func ( *mapType) () *format.LogicalType {
	return &format.LogicalType{Map: (*format.MapType)()}
}

func ( *mapType) () *deprecated.ConvertedType {
	return &convertedTypes[deprecated.Map]
}

func ( *mapType) (int) ColumnIndexer {
	panic("create create column indexer from parquet MAP type")
}

func ( *mapType) (int, int, encoding.Values) Dictionary {
	panic("cannot create dictionary from parquet MAP type")
}

func ( *mapType) (int, int) ColumnBuffer {
	panic("cannot create column buffer from parquet MAP type")
}

func ( *mapType) (int, int, encoding.Values) Page {
	panic("cannot create page from parquet MAP type")
}

func ( *mapType) ( []byte,  []uint32) encoding.Values {
	panic("cannot create values from parquet MAP type")
}

func ( *mapType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	panic("cannot encode parquet MAP type")
}

func ( *mapType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	panic("cannot decode parquet MAP type")
}

func ( *mapType) ( int,  []byte,  encoding.Encoding) int {
	panic("cannot estimate decode size of parquet MAP type")
}

func ( *mapType) (reflect.Value, Value) error {
	panic("cannot assign value to a parquet MAP type")
}

func ( *mapType) (Value, Type) (Value, error) {
	panic("cannot convert value to a parquet MAP type")
}

type nullType format.NullType

func ( *nullType) () string { return (*format.NullType)().String() }

func ( *nullType) () Kind { return -1 }

func ( *nullType) () int { return 0 }

func ( *nullType) (int) int { return 0 }

func ( *nullType) (int) int { return 0 }

func ( *nullType) (Value, Value) int { panic("cannot compare values on parquet NULL type") }

func ( *nullType) () *format.ColumnOrder { return nil }

func ( *nullType) () *format.Type { return nil }

func ( *nullType) () *format.LogicalType {
	return &format.LogicalType{Unknown: (*format.NullType)()}
}

func ( *nullType) () *deprecated.ConvertedType { return nil }

func ( *nullType) (int) ColumnIndexer {
	panic("create create column indexer from parquet NULL type")
}

func ( *nullType) (int, int, encoding.Values) Dictionary {
	panic("cannot create dictionary from parquet NULL type")
}

func ( *nullType) (int, int) ColumnBuffer {
	panic("cannot create column buffer from parquet NULL type")
}

func ( *nullType) (,  int,  encoding.Values) Page {
	return newNullPage(, makeColumnIndex(), makeNumValues())
}

func ( *nullType) ( []byte,  []uint32) encoding.Values {
	return encoding.Values{}
}

func ( *nullType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	return [:0], nil
}

func ( *nullType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	return , nil
}

func ( *nullType) ( int,  []byte,  encoding.Encoding) int {
	return 0
}

func ( *nullType) (reflect.Value, Value) error {
	return nil
}

func ( *nullType) ( Value,  Type) (Value, error) {
	return , nil
}

type groupType struct{}

func (groupType) () string { return "group" }

func (groupType) () Kind {
	panic("cannot call Kind on parquet group")
}

func (groupType) (Value, Value) int {
	panic("cannot compare values on parquet group")
}

func (groupType) (int) ColumnIndexer {
	panic("cannot create column indexer from parquet group")
}

func (groupType) (int, int, encoding.Values) Dictionary {
	panic("cannot create dictionary from parquet group")
}

func ( groupType) (int, int) ColumnBuffer {
	panic("cannot create column buffer from parquet group")
}

func ( groupType) (int, int, encoding.Values) Page {
	panic("cannot create page from parquet group")
}

func ( groupType) ( []byte,  []uint32) encoding.Values {
	panic("cannot create values from parquet group")
}

func (groupType) ( []byte,  encoding.Values,  encoding.Encoding) ([]byte, error) {
	panic("cannot encode parquet group")
}

func (groupType) ( encoding.Values,  []byte,  encoding.Encoding) (encoding.Values, error) {
	panic("cannot decode parquet group")
}

func (groupType) ( int,  []byte,  encoding.Encoding) int {
	panic("cannot estimate decode size of parquet group")
}

func (groupType) (reflect.Value, Value) error {
	panic("cannot assign value to a parquet group")
}

func ( groupType) (Value, Type) (Value, error) {
	panic("cannot convert value to a parquet group")
}

func (groupType) () int { return 0 }

func (groupType) (int) int { return 0 }

func (groupType) (int) int { return 0 }

func (groupType) () *format.ColumnOrder { return nil }

func (groupType) () *format.Type { return nil }

func (groupType) () *format.LogicalType { return nil }

func (groupType) () *deprecated.ConvertedType { return nil }

func checkTypeKindEqual(,  Type) error {
	if .Kind() != .Kind() {
		return fmt.Errorf("cannot convert from parquet value of type %s to %s", , )
	}
	return nil
}