blob: 0f29de085513dc0412e33b29a3fe29f7425d134a [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package parquet
import (
"encoding/binary"
"reflect"
"time"
"unsafe"
)
const (
julianUnixEpoch int64 = 2440588
nanosPerDay int64 = 3600 * 24 * 1000 * 1000 * 1000
// Int96SizeBytes is the number of bytes that make up an Int96
Int96SizeBytes int = 12
)
var (
// Int96Traits provides information about the Int96 type
Int96Traits int96Traits
// ByteArrayTraits provides information about the ByteArray type, which is just an []byte
ByteArrayTraits byteArrayTraits
// FixedLenByteArrayTraits provides information about the FixedLenByteArray type which is just an []byte
FixedLenByteArrayTraits fixedLenByteArrayTraits
// ByteArraySizeBytes is the number of bytes returned by reflect.TypeOf(ByteArray{}).Size()
ByteArraySizeBytes int = int(reflect.TypeOf(ByteArray{}).Size())
// FixedLenByteArraySizeBytes is the number of bytes returned by reflect.TypeOf(FixedLenByteArray{}).Size()
FixedLenByteArraySizeBytes int = int(reflect.TypeOf(FixedLenByteArray{}).Size())
)
// NewInt96 creates a new Int96 from the given 3 uint32 values.
func NewInt96(v [3]uint32) (out Int96) {
binary.LittleEndian.PutUint32(out[0:], v[0])
binary.LittleEndian.PutUint32(out[4:], v[1])
binary.LittleEndian.PutUint32(out[8:], v[2])
return
}
// Int96 is a 12 byte integer value utilized for representing timestamps as a 64 bit integer and a 32 bit
// integer.
type Int96 [12]byte
// SetNanoSeconds sets the Nanosecond field of the Int96 timestamp to the provided value
func (i96 *Int96) SetNanoSeconds(nanos int64) {
binary.LittleEndian.PutUint64(i96[:8], uint64(nanos))
}
// String provides the string representation as a timestamp via converting to a time.Time
// and then calling String
func (i96 Int96) String() string {
return i96.ToTime().String()
}
// ToTime returns a go time.Time object that represents the same time instant as the given Int96 value
func (i96 Int96) ToTime() time.Time {
nanos := binary.LittleEndian.Uint64(i96[:8])
jdays := binary.LittleEndian.Uint32(i96[8:])
nanos = (uint64(jdays)-uint64(julianUnixEpoch))*uint64(nanosPerDay) + nanos
t := time.Unix(0, int64(nanos))
return t.UTC()
}
type int96Traits struct{}
func (int96Traits) BytesRequired(n int) int { return Int96SizeBytes * n }
func (int96Traits) CastFromBytes(b []byte) []Int96 {
h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
var res []Int96
s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
s.Data = h.Data
s.Len = h.Len / Int96SizeBytes
s.Cap = h.Cap / Int96SizeBytes
return res
}
func (int96Traits) CastToBytes(b []Int96) []byte {
h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
var res []byte
s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
s.Data = h.Data
s.Len = h.Len * Int96SizeBytes
s.Cap = h.Cap * Int96SizeBytes
return res
}
// ByteArray is a type to be utilized for representing the Parquet ByteArray physical type, represented as a byte slice
type ByteArray []byte
// Len returns the current length of the ByteArray, equivalent to len(bytearray)
func (b ByteArray) Len() int {
return len(b)
}
// String returns a string representation of the ByteArray
func (b ByteArray) String() string {
return *(*string)(unsafe.Pointer(&b))
}
type byteArrayTraits struct{}
func (byteArrayTraits) BytesRequired(n int) int {
return ByteArraySizeBytes * n
}
func (byteArrayTraits) CastFromBytes(b []byte) []ByteArray {
h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
var res []ByteArray
s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
s.Data = h.Data
s.Len = h.Len / ByteArraySizeBytes
s.Cap = h.Cap / ByteArraySizeBytes
return res
}
// FixedLenByteArray is a go type to represent a FixedLengthByteArray as a byte slice
type FixedLenByteArray []byte
// Len returns the current length of this FixedLengthByteArray, equivalent to len(fixedlenbytearray)
func (b FixedLenByteArray) Len() int {
return len(b)
}
// String returns a string representation of the FixedLenByteArray
func (b FixedLenByteArray) String() string {
return *(*string)(unsafe.Pointer(&b))
}
type fixedLenByteArrayTraits struct{}
func (fixedLenByteArrayTraits) BytesRequired(n int) int {
return FixedLenByteArraySizeBytes * n
}
func (fixedLenByteArrayTraits) CastFromBytes(b []byte) []FixedLenByteArray {
h := (*reflect.SliceHeader)(unsafe.Pointer(&b))
var res []FixedLenByteArray
s := (*reflect.SliceHeader)(unsafe.Pointer(&res))
s.Data = h.Data
s.Len = h.Len / FixedLenByteArraySizeBytes
s.Cap = h.Cap / FixedLenByteArraySizeBytes
return res
}