// Copyright 2019 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package filedesc

import (
	"sync"

	"google.golang.org/protobuf/encoding/protowire"
	"google.golang.org/protobuf/internal/genid"
	"google.golang.org/protobuf/internal/strs"
	pref "google.golang.org/protobuf/reflect/protoreflect"
)

// fileRaw is a data struct used when initializing a file descriptor from
// a raw FileDescriptorProto.
type fileRaw struct {
	builder       Builder
	allEnums      []Enum
	allMessages   []Message
	allExtensions []Extension
	allServices   []Service
}

func newRawFile(db Builder) *File {
	fd := &File{fileRaw: fileRaw{builder: db}}
	fd.initDecls(db.NumEnums, db.NumMessages, db.NumExtensions, db.NumServices)
	fd.unmarshalSeed(db.RawDescriptor)

	// Extended message targets are eagerly resolved since registration
	// needs this information at program init time.
	for i := range fd.allExtensions {
		xd := &fd.allExtensions[i]
		xd.L1.Extendee = fd.resolveMessageDependency(xd.L1.Extendee, listExtTargets, int32(i))
	}

	fd.checkDecls()
	return fd
}

// initDecls pre-allocates slices for the exact number of enums, messages
// (including map entries), extensions, and services declared in the proto file.
// This is done to avoid regrowing the slice, which would change the address
// for any previously seen declaration.
//
// The alloc methods "allocates" slices by pulling from the capacity.
func (fd *File) initDecls(numEnums, numMessages, numExtensions, numServices int32) {
	fd.allEnums = make([]Enum, 0, numEnums)
	fd.allMessages = make([]Message, 0, numMessages)
	fd.allExtensions = make([]Extension, 0, numExtensions)
	fd.allServices = make([]Service, 0, numServices)
}

func (fd *File) allocEnums(n int) []Enum {
	total := len(fd.allEnums)
	es := fd.allEnums[total : total+n]
	fd.allEnums = fd.allEnums[:total+n]
	return es
}
func (fd *File) allocMessages(n int) []Message {
	total := len(fd.allMessages)
	ms := fd.allMessages[total : total+n]
	fd.allMessages = fd.allMessages[:total+n]
	return ms
}
func (fd *File) allocExtensions(n int) []Extension {
	total := len(fd.allExtensions)
	xs := fd.allExtensions[total : total+n]
	fd.allExtensions = fd.allExtensions[:total+n]
	return xs
}
func (fd *File) allocServices(n int) []Service {
	total := len(fd.allServices)
	xs := fd.allServices[total : total+n]
	fd.allServices = fd.allServices[:total+n]
	return xs
}

// checkDecls performs a sanity check that the expected number of expected
// declarations matches the number that were found in the descriptor proto.
func (fd *File) checkDecls() {
	switch {
	case len(fd.allEnums) != cap(fd.allEnums):
	case len(fd.allMessages) != cap(fd.allMessages):
	case len(fd.allExtensions) != cap(fd.allExtensions):
	case len(fd.allServices) != cap(fd.allServices):
	default:
		return
	}
	panic("mismatching cardinality")
}

func (fd *File) unmarshalSeed(b []byte) {
	sb := getBuilder()
	defer putBuilder(sb)

	var prevField pref.FieldNumber
	var numEnums, numMessages, numExtensions, numServices int
	var posEnums, posMessages, posExtensions, posServices int
	b0 := b
	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.FileDescriptorProto_Syntax_field_number:
				switch string(v) {
				case "proto2":
					fd.L1.Syntax = pref.Proto2
				case "proto3":
					fd.L1.Syntax = pref.Proto3
				default:
					panic("invalid syntax")
				}
			case genid.FileDescriptorProto_Name_field_number:
				fd.L1.Path = sb.MakeString(v)
			case genid.FileDescriptorProto_Package_field_number:
				fd.L1.Package = pref.FullName(sb.MakeString(v))
			case genid.FileDescriptorProto_EnumType_field_number:
				if prevField != genid.FileDescriptorProto_EnumType_field_number {
					if numEnums > 0 {
						panic("non-contiguous repeated field")
					}
					posEnums = len(b0) - len(b) - n - m
				}
				numEnums++
			case genid.FileDescriptorProto_MessageType_field_number:
				if prevField != genid.FileDescriptorProto_MessageType_field_number {
					if numMessages > 0 {
						panic("non-contiguous repeated field")
					}
					posMessages = len(b0) - len(b) - n - m
				}
				numMessages++
			case genid.FileDescriptorProto_Extension_field_number:
				if prevField != genid.FileDescriptorProto_Extension_field_number {
					if numExtensions > 0 {
						panic("non-contiguous repeated field")
					}
					posExtensions = len(b0) - len(b) - n - m
				}
				numExtensions++
			case genid.FileDescriptorProto_Service_field_number:
				if prevField != genid.FileDescriptorProto_Service_field_number {
					if numServices > 0 {
						panic("non-contiguous repeated field")
					}
					posServices = len(b0) - len(b) - n - m
				}
				numServices++
			}
			prevField = num
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
			prevField = -1 // ignore known field numbers of unknown wire type
		}
	}

	// If syntax is missing, it is assumed to be proto2.
	if fd.L1.Syntax == 0 {
		fd.L1.Syntax = pref.Proto2
	}

	// Must allocate all declarations before parsing each descriptor type
	// to ensure we handled all descriptors in "flattened ordering".
	if numEnums > 0 {
		fd.L1.Enums.List = fd.allocEnums(numEnums)
	}
	if numMessages > 0 {
		fd.L1.Messages.List = fd.allocMessages(numMessages)
	}
	if numExtensions > 0 {
		fd.L1.Extensions.List = fd.allocExtensions(numExtensions)
	}
	if numServices > 0 {
		fd.L1.Services.List = fd.allocServices(numServices)
	}

	if numEnums > 0 {
		b := b0[posEnums:]
		for i := range fd.L1.Enums.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			fd.L1.Enums.List[i].unmarshalSeed(v, sb, fd, fd, i)
			b = b[n+m:]
		}
	}
	if numMessages > 0 {
		b := b0[posMessages:]
		for i := range fd.L1.Messages.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			fd.L1.Messages.List[i].unmarshalSeed(v, sb, fd, fd, i)
			b = b[n+m:]
		}
	}
	if numExtensions > 0 {
		b := b0[posExtensions:]
		for i := range fd.L1.Extensions.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			fd.L1.Extensions.List[i].unmarshalSeed(v, sb, fd, fd, i)
			b = b[n+m:]
		}
	}
	if numServices > 0 {
		b := b0[posServices:]
		for i := range fd.L1.Services.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			fd.L1.Services.List[i].unmarshalSeed(v, sb, fd, fd, i)
			b = b[n+m:]
		}
	}
}

func (ed *Enum) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
	ed.L0.ParentFile = pf
	ed.L0.Parent = pd
	ed.L0.Index = i

	var numValues int
	for b := b; len(b) > 0; {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.EnumDescriptorProto_Name_field_number:
				ed.L0.FullName = appendFullName(sb, pd.FullName(), v)
			case genid.EnumDescriptorProto_Value_field_number:
				numValues++
			}
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
		}
	}

	// Only construct enum value descriptors for top-level enums since
	// they are needed for registration.
	if pd != pf {
		return
	}
	ed.L1.eagerValues = true
	ed.L2 = new(EnumL2)
	ed.L2.Values.List = make([]EnumValue, numValues)
	for i := 0; len(b) > 0; {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.EnumDescriptorProto_Value_field_number:
				ed.L2.Values.List[i].unmarshalFull(v, sb, pf, ed, i)
				i++
			}
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
		}
	}
}

func (md *Message) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
	md.L0.ParentFile = pf
	md.L0.Parent = pd
	md.L0.Index = i

	var prevField pref.FieldNumber
	var numEnums, numMessages, numExtensions int
	var posEnums, posMessages, posExtensions int
	b0 := b
	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.DescriptorProto_Name_field_number:
				md.L0.FullName = appendFullName(sb, pd.FullName(), v)
			case genid.DescriptorProto_EnumType_field_number:
				if prevField != genid.DescriptorProto_EnumType_field_number {
					if numEnums > 0 {
						panic("non-contiguous repeated field")
					}
					posEnums = len(b0) - len(b) - n - m
				}
				numEnums++
			case genid.DescriptorProto_NestedType_field_number:
				if prevField != genid.DescriptorProto_NestedType_field_number {
					if numMessages > 0 {
						panic("non-contiguous repeated field")
					}
					posMessages = len(b0) - len(b) - n - m
				}
				numMessages++
			case genid.DescriptorProto_Extension_field_number:
				if prevField != genid.DescriptorProto_Extension_field_number {
					if numExtensions > 0 {
						panic("non-contiguous repeated field")
					}
					posExtensions = len(b0) - len(b) - n - m
				}
				numExtensions++
			case genid.DescriptorProto_Options_field_number:
				md.unmarshalSeedOptions(v)
			}
			prevField = num
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
			prevField = -1 // ignore known field numbers of unknown wire type
		}
	}

	// Must allocate all declarations before parsing each descriptor type
	// to ensure we handled all descriptors in "flattened ordering".
	if numEnums > 0 {
		md.L1.Enums.List = pf.allocEnums(numEnums)
	}
	if numMessages > 0 {
		md.L1.Messages.List = pf.allocMessages(numMessages)
	}
	if numExtensions > 0 {
		md.L1.Extensions.List = pf.allocExtensions(numExtensions)
	}

	if numEnums > 0 {
		b := b0[posEnums:]
		for i := range md.L1.Enums.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			md.L1.Enums.List[i].unmarshalSeed(v, sb, pf, md, i)
			b = b[n+m:]
		}
	}
	if numMessages > 0 {
		b := b0[posMessages:]
		for i := range md.L1.Messages.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			md.L1.Messages.List[i].unmarshalSeed(v, sb, pf, md, i)
			b = b[n+m:]
		}
	}
	if numExtensions > 0 {
		b := b0[posExtensions:]
		for i := range md.L1.Extensions.List {
			_, n := protowire.ConsumeVarint(b)
			v, m := protowire.ConsumeBytes(b[n:])
			md.L1.Extensions.List[i].unmarshalSeed(v, sb, pf, md, i)
			b = b[n+m:]
		}
	}
}

func (md *Message) unmarshalSeedOptions(b []byte) {
	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.VarintType:
			v, m := protowire.ConsumeVarint(b)
			b = b[m:]
			switch num {
			case genid.MessageOptions_MapEntry_field_number:
				md.L1.IsMapEntry = protowire.DecodeBool(v)
			case genid.MessageOptions_MessageSetWireFormat_field_number:
				md.L1.IsMessageSet = protowire.DecodeBool(v)
			}
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
		}
	}
}

func (xd *Extension) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
	xd.L0.ParentFile = pf
	xd.L0.Parent = pd
	xd.L0.Index = i

	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.VarintType:
			v, m := protowire.ConsumeVarint(b)
			b = b[m:]
			switch num {
			case genid.FieldDescriptorProto_Number_field_number:
				xd.L1.Number = pref.FieldNumber(v)
			case genid.FieldDescriptorProto_Label_field_number:
				xd.L1.Cardinality = pref.Cardinality(v)
			case genid.FieldDescriptorProto_Type_field_number:
				xd.L1.Kind = pref.Kind(v)
			}
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.FieldDescriptorProto_Name_field_number:
				xd.L0.FullName = appendFullName(sb, pd.FullName(), v)
			case genid.FieldDescriptorProto_Extendee_field_number:
				xd.L1.Extendee = PlaceholderMessage(makeFullName(sb, v))
			}
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
		}
	}
}

func (sd *Service) unmarshalSeed(b []byte, sb *strs.Builder, pf *File, pd pref.Descriptor, i int) {
	sd.L0.ParentFile = pf
	sd.L0.Parent = pd
	sd.L0.Index = i

	for len(b) > 0 {
		num, typ, n := protowire.ConsumeTag(b)
		b = b[n:]
		switch typ {
		case protowire.BytesType:
			v, m := protowire.ConsumeBytes(b)
			b = b[m:]
			switch num {
			case genid.ServiceDescriptorProto_Name_field_number:
				sd.L0.FullName = appendFullName(sb, pd.FullName(), v)
			}
		default:
			m := protowire.ConsumeFieldValue(num, typ, b)
			b = b[m:]
		}
	}
}

var nameBuilderPool = sync.Pool{
	New: func() interface{} { return new(strs.Builder) },
}

func getBuilder() *strs.Builder {
	return nameBuilderPool.Get().(*strs.Builder)
}
func putBuilder(b *strs.Builder) {
	nameBuilderPool.Put(b)
}

// makeFullName converts b to a protoreflect.FullName,
// where b must start with a leading dot.
func makeFullName(sb *strs.Builder, b []byte) pref.FullName {
	if len(b) == 0 || b[0] != '.' {
		panic("name reference must be fully qualified")
	}
	return pref.FullName(sb.MakeString(b[1:]))
}

func appendFullName(sb *strs.Builder, prefix pref.FullName, suffix []byte) pref.FullName {
	return sb.AppendFullName(prefix, pref.Name(strs.UnsafeString(suffix)))
}
