// 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 arrow

import (
	
	

	
	
	
)

const (
	ViewPrefixLen  = 4
	viewInlineSize = 12
)

func ( int) bool {
	return  < viewInlineSize
}

// ViewHeader is a variable length string (utf8) or byte slice with
// a 4 byte prefix and inline optimization for small values (12 bytes
// or fewer). This is similar to Go's standard string but limited by
// a length of Uint32Max and up to the first four bytes of the string
// are copied into the struct. This prefix allows failing comparisons
// early and can reduce CPU cache working set when dealing with short
// strings.
//
// There are two situations:
//
//		Entirely inlined string data
//	                |----|------------|
//		                ^    ^
//		                |    |
//		              size  inline string data, zero padded
//
//		Reference into buffer
//	                |----|----|----|----|
//		                ^    ^     ^     ^
//		                |    |     |     |
//		              size prefix buffer index and offset to out-of-line portion
//
// Adapted from TU Munich's UmbraDB [1], Velox, DuckDB.
//
// [1]: https://db.in.tum.de/~freitag/papers/p29-neumann-cidr20.pdf
type ViewHeader struct {
	size int32
	// the first 4 bytes of this are the prefix for the string
	// if size <= StringHeaderInlineSize, then the entire string
	// is in the data array and is zero padded.
	// if size > StringHeaderInlineSize, the next 8 bytes are 2 uint32
	// values which are the buffer index and offset in that buffer
	// containing the full string.
	data [viewInlineSize]byte
}

func ( *ViewHeader) () bool {
	return .size <= int32(viewInlineSize)
}

func ( *ViewHeader) () int { return int(.size) }
func ( *ViewHeader) () [ViewPrefixLen]byte {
	return *(*[4]byte)(unsafe.Pointer(&.data))
}

func ( *ViewHeader) () int32 {
	return int32(endian.Native.Uint32(.data[ViewPrefixLen:]))
}

func ( *ViewHeader) () int32 {
	return int32(endian.Native.Uint32(.data[ViewPrefixLen+4:]))
}

func ( *ViewHeader) () ( []byte) {
	debug.Assert(.IsInline(), "calling InlineBytes on non-inline ViewHeader")
	return .data[:.size]
}

func ( *ViewHeader) ( []byte) int {
	.size = int32(len())
	if .IsInline() {
		return copy(.data[:], )
	}
	return copy(.data[:4], )
}

func ( *ViewHeader) ( string) int {
	.size = int32(len())
	if .IsInline() {
		return copy(.data[:], )
	}
	return copy(.data[:4], )
}

func ( *ViewHeader) (,  int32) {
	endian.Native.PutUint32(.data[ViewPrefixLen:], uint32())
	endian.Native.PutUint32(.data[ViewPrefixLen+4:], uint32())
}

func ( *ViewHeader) ( []*memory.Buffer,  *ViewHeader,  []*memory.Buffer) bool {
	if .sizeAndPrefixAsInt64() != .sizeAndPrefixAsInt64() {
		return false
	}

	if .IsInline() {
		return .inlinedAsInt64() == .inlinedAsInt64()
	}

	return bytes.Equal(.getBufferBytes(), .getBufferBytes())
}

func ( *ViewHeader) ( []*memory.Buffer) []byte {
	 := .BufferOffset()
	return [.BufferIndex()].Bytes()[ : +.size]
}

func ( *ViewHeader) () int64 {
	 := unsafe.Slice((*int64)(unsafe.Pointer()), 2)
	return [1]
}

func ( *ViewHeader) () int64 {
	 := unsafe.Slice((*int64)(unsafe.Pointer()), 2)
	return [0]
}