// SPDX-License-Identifier: Unlicense OR BSD-3-Clause

package tables

import (
	"encoding/binary"
	"fmt"
)

// Code generated by binarygen from kern_src.go. DO NOT EDIT

func ParseAATKernSubtableHeader(src []byte) (AATKernSubtableHeader, int, error) {
	var item AATKernSubtableHeader
	n := 0
	if L := len(src); L < 8 {
		return item, 0, fmt.Errorf("reading AATKernSubtableHeader: "+"EOF: expected length: 8, got %d", L)
	}
	_ = src[7] // early bound checking
	item.length = binary.BigEndian.Uint32(src[0:])
	item.Coverage = src[4]
	item.version = kernSTVersion(src[5])
	item.TupleCount = binary.BigEndian.Uint16(src[6:])
	n += 8

	{
		var (
			read int
			err  error
		)
		switch item.version {
		case kernSTVersion0:
			item.data, read, err = ParseKernData0(src[8:])
		case kernSTVersion1:
			item.data, read, err = ParseKernData1(src[8:])
		case kernSTVersion2:
			item.data, read, err = ParseKernData2(src[8:], src)
		case kernSTVersion3:
			item.data, read, err = ParseKernData3(src[8:])
		default:
			err = fmt.Errorf("unsupported KernDataVersion %d", item.version)
		}
		if err != nil {
			return item, 0, fmt.Errorf("reading AATKernSubtableHeader: %s", err)
		}
		n += read
	}
	var err error
	n, err = item.parseEnd(src)
	if err != nil {
		return item, 0, fmt.Errorf("reading AATKernSubtableHeader: %s", err)
	}

	return item, n, nil
}

func ParseAATStateTable(src []byte) (AATStateTable, int, error) {
	var item AATStateTable
	n := 0
	if L := len(src); L < 8 {
		return item, 0, fmt.Errorf("reading AATStateTable: "+"EOF: expected length: 8, got %d", L)
	}
	_ = src[7] // early bound checking
	item.StateSize = binary.BigEndian.Uint16(src[0:])
	offsetClassTable := int(binary.BigEndian.Uint16(src[2:]))
	item.stateArray = Offset16(binary.BigEndian.Uint16(src[4:]))
	item.entryTable = Offset16(binary.BigEndian.Uint16(src[6:]))
	n += 8

	{
		if offsetClassTable != 0 { // ignore null offset
			if L := len(src); L < offsetClassTable {
				return item, 0, fmt.Errorf("reading AATStateTable: "+"EOF: expected length: %d, got %d", offsetClassTable, L)
			}

			var err error
			item.ClassTable, _, err = ParseClassTable(src[offsetClassTable:])
			if err != nil {
				return item, 0, fmt.Errorf("reading AATStateTable: %s", err)
			}

		}
	}
	{

		err := item.parseStates(src[:])
		if err != nil {
			return item, 0, fmt.Errorf("reading AATStateTable: %s", err)
		}
	}
	{

		read, err := item.parseEntries(src[:])
		if err != nil {
			return item, 0, fmt.Errorf("reading AATStateTable: %s", err)
		}
		n = read
	}
	return item, n, nil
}

func ParseClassTable(src []byte) (ClassTable, int, error) {
	var item ClassTable
	n := 0
	if L := len(src); L < 4 {
		return item, 0, fmt.Errorf("reading ClassTable: "+"EOF: expected length: 4, got %d", L)
	}
	_ = src[3] // early bound checking
	item.StartGlyph = binary.BigEndian.Uint16(src[0:])
	arrayLengthValues := int(binary.BigEndian.Uint16(src[2:]))
	n += 4

	{

		L := int(4 + arrayLengthValues)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading ClassTable: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.Values = src[4:L]
		n = L
	}
	return item, n, nil
}

func ParseKernData0(src []byte) (KernData0, int, error) {
	var item KernData0
	n := 0
	if L := len(src); L < 8 {
		return item, 0, fmt.Errorf("reading KernData0: "+"EOF: expected length: 8, got %d", L)
	}
	_ = src[7] // early bound checking
	item.nPairs = binary.BigEndian.Uint16(src[0:])
	item.searchRange = binary.BigEndian.Uint16(src[2:])
	item.entrySelector = binary.BigEndian.Uint16(src[4:])
	item.rangeShift = binary.BigEndian.Uint16(src[6:])
	n += 8

	{
		arrayLength := int(item.nPairs)

		if L := len(src); L < 8+arrayLength*6 {
			return item, 0, fmt.Errorf("reading KernData0: "+"EOF: expected length: %d, got %d", 8+arrayLength*6, L)
		}

		item.Pairs = make([]Kernx0Record, arrayLength) // allocation guarded by the previous check
		for i := range item.Pairs {
			item.Pairs[i].mustParse(src[8+i*6:])
		}
		n += arrayLength * 6
	}
	return item, n, nil
}

func ParseKernData1(src []byte) (KernData1, int, error) {
	var item KernData1
	n := 0
	{
		var (
			err  error
			read int
		)
		item.AATStateTable, read, err = ParseAATStateTable(src[0:])
		if err != nil {
			return item, 0, fmt.Errorf("reading KernData1: %s", err)
		}
		n += read
	}
	if L := len(src); L < n+2 {
		return item, 0, fmt.Errorf("reading KernData1: "+"EOF: expected length: n + 2, got %d", L)
	}
	item.valueTable = binary.BigEndian.Uint16(src[n:])
	n += 2

	{

		err := item.parseValues(src[:])
		if err != nil {
			return item, 0, fmt.Errorf("reading KernData1: %s", err)
		}
	}
	return item, n, nil
}

func ParseKernData2(src []byte, parentSrc []byte) (KernData2, int, error) {
	var item KernData2
	n := 0
	if L := len(src); L < 8 {
		return item, 0, fmt.Errorf("reading KernData2: "+"EOF: expected length: 8, got %d", L)
	}
	_ = src[7] // early bound checking
	item.rowWidth = binary.BigEndian.Uint16(src[0:])
	offsetLeft := int(binary.BigEndian.Uint16(src[2:]))
	offsetRight := int(binary.BigEndian.Uint16(src[4:]))
	item.KerningStart = Offset16(binary.BigEndian.Uint16(src[6:]))
	n += 8

	{
		if offsetLeft != 0 { // ignore null offset
			if L := len(parentSrc); L < offsetLeft {
				return item, 0, fmt.Errorf("reading KernData2: "+"EOF: expected length: %d, got %d", offsetLeft, L)
			}

			var err error
			item.Left, _, err = ParseAATLoopkup8Data(parentSrc[offsetLeft:])
			if err != nil {
				return item, 0, fmt.Errorf("reading KernData2: %s", err)
			}

		}
	}
	{
		if offsetRight != 0 { // ignore null offset
			if L := len(parentSrc); L < offsetRight {
				return item, 0, fmt.Errorf("reading KernData2: "+"EOF: expected length: %d, got %d", offsetRight, L)
			}

			var err error
			item.Right, _, err = ParseAATLoopkup8Data(parentSrc[offsetRight:])
			if err != nil {
				return item, 0, fmt.Errorf("reading KernData2: %s", err)
			}

		}
	}
	{

		err := item.parseKerningData(src[:], parentSrc)
		if err != nil {
			return item, 0, fmt.Errorf("reading KernData2: %s", err)
		}
	}
	return item, n, nil
}

func ParseKernData3(src []byte) (KernData3, int, error) {
	var item KernData3
	n := 0
	if L := len(src); L < 6 {
		return item, 0, fmt.Errorf("reading KernData3: "+"EOF: expected length: 6, got %d", L)
	}
	_ = src[5] // early bound checking
	item.glyphCount = binary.BigEndian.Uint16(src[0:])
	item.kernValueCount = src[2]
	item.leftClassCount = src[3]
	item.RightClassCount = src[4]
	item.flags = src[5]
	n += 6

	{
		arrayLength := int(item.kernValueCount)

		if L := len(src); L < 6+arrayLength*2 {
			return item, 0, fmt.Errorf("reading KernData3: "+"EOF: expected length: %d, got %d", 6+arrayLength*2, L)
		}

		item.Kernings = make([]int16, arrayLength) // allocation guarded by the previous check
		for i := range item.Kernings {
			item.Kernings[i] = int16(binary.BigEndian.Uint16(src[6+i*2:]))
		}
		n += arrayLength * 2
	}
	{
		arrayLength := int(item.glyphCount)

		L := int(n + arrayLength)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading KernData3: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.LeftClass = src[n:L]
		n = L
	}
	{
		arrayLength := int(item.glyphCount)

		L := int(n + arrayLength)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading KernData3: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.RightClass = src[n:L]
		n = L
	}
	{
		arrayLength := int(item.nKernIndex())

		L := int(n + arrayLength)
		if len(src) < L {
			return item, 0, fmt.Errorf("reading KernData3: "+"EOF: expected length: %d, got %d", L, len(src))
		}
		item.KernIndex = src[n:L]
		n = L
	}
	var err error
	n, err = item.parseEnd(src)
	if err != nil {
		return item, 0, fmt.Errorf("reading KernData3: %s", err)
	}

	return item, n, nil
}

func ParseOTKernSubtableHeader(src []byte) (OTKernSubtableHeader, int, error) {
	var item OTKernSubtableHeader
	n := 0
	if L := len(src); L < 6 {
		return item, 0, fmt.Errorf("reading OTKernSubtableHeader: "+"EOF: expected length: 6, got %d", L)
	}
	_ = src[5] // early bound checking
	item.version = binary.BigEndian.Uint16(src[0:])
	item.length = binary.BigEndian.Uint16(src[2:])
	item.format = kernSTVersion(src[4])
	item.Coverage = src[5]
	n += 6

	{
		var (
			read int
			err  error
		)
		switch item.format {
		case kernSTVersion0:
			item.data, read, err = ParseKernData0(src[6:])
		case kernSTVersion1:
			item.data, read, err = ParseKernData1(src[6:])
		case kernSTVersion2:
			item.data, read, err = ParseKernData2(src[6:], src)
		case kernSTVersion3:
			item.data, read, err = ParseKernData3(src[6:])
		default:
			err = fmt.Errorf("unsupported KernDataVersion %d", item.format)
		}
		if err != nil {
			return item, 0, fmt.Errorf("reading OTKernSubtableHeader: %s", err)
		}
		n += read
	}
	var err error
	n, err = item.parseEnd(src)
	if err != nil {
		return item, 0, fmt.Errorf("reading OTKernSubtableHeader: %s", err)
	}

	return item, n, nil
}
