// Copyright The OpenTelemetry Authors
//
// Licensed 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.

// Code generated by "cmd/pdatagen/main.go". DO NOT EDIT.
// To regenerate this file run "go run cmd/pdatagen/main.go".

package pdata

import (
	"sort"

	otlpmetrics "go.opentelemetry.io/collector/model/internal/data/protogen/metrics/v1"
)

// ResourceMetricsSlice logically represents a slice of ResourceMetrics.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewResourceMetricsSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ResourceMetricsSlice struct {
	// orig points to the slice otlpmetrics.ResourceMetrics field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.ResourceMetrics
}

func newResourceMetricsSlice(orig *[]*otlpmetrics.ResourceMetrics) ResourceMetricsSlice {
	return ResourceMetricsSlice{orig}
}

// NewResourceMetricsSlice creates a ResourceMetricsSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewResourceMetricsSlice() ResourceMetricsSlice {
	orig := []*otlpmetrics.ResourceMetrics(nil)
	return ResourceMetricsSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewResourceMetricsSlice()".
func (es ResourceMetricsSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es ResourceMetricsSlice) At(ix int) ResourceMetrics {
	return newResourceMetrics((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es ResourceMetricsSlice) CopyTo(dest ResourceMetricsSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newResourceMetrics((*es.orig)[i]).CopyTo(newResourceMetrics((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.ResourceMetrics, srcLen)
	wrappers := make([]*otlpmetrics.ResourceMetrics, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newResourceMetrics((*es.orig)[i]).CopyTo(newResourceMetrics(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new ResourceMetricsSlice can be initialized:
//   es := NewResourceMetricsSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es ResourceMetricsSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.ResourceMetrics, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty ResourceMetrics.
// It returns the newly added ResourceMetrics.
func (es ResourceMetricsSlice) AppendEmpty() ResourceMetrics {
	*es.orig = append(*es.orig, &otlpmetrics.ResourceMetrics{})
	return es.At(es.Len() - 1)
}

// Sort sorts the ResourceMetrics elements within ResourceMetricsSlice given the
// provided less function so that two instances of ResourceMetricsSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b ResourceMetrics) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es ResourceMetricsSlice) Sort(less func(a, b ResourceMetrics) bool) ResourceMetricsSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ResourceMetricsSlice) MoveAndAppendTo(dest ResourceMetricsSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ResourceMetricsSlice) RemoveIf(f func(ResourceMetrics) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// ResourceMetrics is a collection of metrics from a Resource.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewResourceMetrics function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type ResourceMetrics struct {
	orig *otlpmetrics.ResourceMetrics
}

func newResourceMetrics(orig *otlpmetrics.ResourceMetrics) ResourceMetrics {
	return ResourceMetrics{orig: orig}
}

// NewResourceMetrics creates a new empty ResourceMetrics.
//
// This must be used only in testing code since no "Set" method available.
func NewResourceMetrics() ResourceMetrics {
	return newResourceMetrics(&otlpmetrics.ResourceMetrics{})
}

// Resource returns the resource associated with this ResourceMetrics.
func (ms ResourceMetrics) Resource() Resource {
	return newResource(&(*ms.orig).Resource)
}

// InstrumentationLibraryMetrics returns the InstrumentationLibraryMetrics associated with this ResourceMetrics.
func (ms ResourceMetrics) InstrumentationLibraryMetrics() InstrumentationLibraryMetricsSlice {
	return newInstrumentationLibraryMetricsSlice(&(*ms.orig).InstrumentationLibraryMetrics)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms ResourceMetrics) CopyTo(dest ResourceMetrics) {
	ms.Resource().CopyTo(dest.Resource())
	ms.InstrumentationLibraryMetrics().CopyTo(dest.InstrumentationLibraryMetrics())
}

// InstrumentationLibraryMetricsSlice logically represents a slice of InstrumentationLibraryMetrics.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewInstrumentationLibraryMetricsSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type InstrumentationLibraryMetricsSlice struct {
	// orig points to the slice otlpmetrics.InstrumentationLibraryMetrics field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.InstrumentationLibraryMetrics
}

func newInstrumentationLibraryMetricsSlice(orig *[]*otlpmetrics.InstrumentationLibraryMetrics) InstrumentationLibraryMetricsSlice {
	return InstrumentationLibraryMetricsSlice{orig}
}

// NewInstrumentationLibraryMetricsSlice creates a InstrumentationLibraryMetricsSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewInstrumentationLibraryMetricsSlice() InstrumentationLibraryMetricsSlice {
	orig := []*otlpmetrics.InstrumentationLibraryMetrics(nil)
	return InstrumentationLibraryMetricsSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewInstrumentationLibraryMetricsSlice()".
func (es InstrumentationLibraryMetricsSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es InstrumentationLibraryMetricsSlice) At(ix int) InstrumentationLibraryMetrics {
	return newInstrumentationLibraryMetrics((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es InstrumentationLibraryMetricsSlice) CopyTo(dest InstrumentationLibraryMetricsSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newInstrumentationLibraryMetrics((*es.orig)[i]).CopyTo(newInstrumentationLibraryMetrics((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.InstrumentationLibraryMetrics, srcLen)
	wrappers := make([]*otlpmetrics.InstrumentationLibraryMetrics, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newInstrumentationLibraryMetrics((*es.orig)[i]).CopyTo(newInstrumentationLibraryMetrics(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new InstrumentationLibraryMetricsSlice can be initialized:
//   es := NewInstrumentationLibraryMetricsSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es InstrumentationLibraryMetricsSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.InstrumentationLibraryMetrics, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty InstrumentationLibraryMetrics.
// It returns the newly added InstrumentationLibraryMetrics.
func (es InstrumentationLibraryMetricsSlice) AppendEmpty() InstrumentationLibraryMetrics {
	*es.orig = append(*es.orig, &otlpmetrics.InstrumentationLibraryMetrics{})
	return es.At(es.Len() - 1)
}

// Sort sorts the InstrumentationLibraryMetrics elements within InstrumentationLibraryMetricsSlice given the
// provided less function so that two instances of InstrumentationLibraryMetricsSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b InstrumentationLibraryMetrics) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es InstrumentationLibraryMetricsSlice) Sort(less func(a, b InstrumentationLibraryMetrics) bool) InstrumentationLibraryMetricsSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es InstrumentationLibraryMetricsSlice) MoveAndAppendTo(dest InstrumentationLibraryMetricsSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es InstrumentationLibraryMetricsSlice) RemoveIf(f func(InstrumentationLibraryMetrics) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// InstrumentationLibraryMetrics is a collection of metrics from a LibraryInstrumentation.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewInstrumentationLibraryMetrics function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type InstrumentationLibraryMetrics struct {
	orig *otlpmetrics.InstrumentationLibraryMetrics
}

func newInstrumentationLibraryMetrics(orig *otlpmetrics.InstrumentationLibraryMetrics) InstrumentationLibraryMetrics {
	return InstrumentationLibraryMetrics{orig: orig}
}

// NewInstrumentationLibraryMetrics creates a new empty InstrumentationLibraryMetrics.
//
// This must be used only in testing code since no "Set" method available.
func NewInstrumentationLibraryMetrics() InstrumentationLibraryMetrics {
	return newInstrumentationLibraryMetrics(&otlpmetrics.InstrumentationLibraryMetrics{})
}

// InstrumentationLibrary returns the instrumentationlibrary associated with this InstrumentationLibraryMetrics.
func (ms InstrumentationLibraryMetrics) InstrumentationLibrary() InstrumentationLibrary {
	return newInstrumentationLibrary(&(*ms.orig).InstrumentationLibrary)
}

// Metrics returns the Metrics associated with this InstrumentationLibraryMetrics.
func (ms InstrumentationLibraryMetrics) Metrics() MetricSlice {
	return newMetricSlice(&(*ms.orig).Metrics)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms InstrumentationLibraryMetrics) CopyTo(dest InstrumentationLibraryMetrics) {
	ms.InstrumentationLibrary().CopyTo(dest.InstrumentationLibrary())
	ms.Metrics().CopyTo(dest.Metrics())
}

// MetricSlice logically represents a slice of Metric.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewMetricSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type MetricSlice struct {
	// orig points to the slice otlpmetrics.Metric field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.Metric
}

func newMetricSlice(orig *[]*otlpmetrics.Metric) MetricSlice {
	return MetricSlice{orig}
}

// NewMetricSlice creates a MetricSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewMetricSlice() MetricSlice {
	orig := []*otlpmetrics.Metric(nil)
	return MetricSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewMetricSlice()".
func (es MetricSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es MetricSlice) At(ix int) Metric {
	return newMetric((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es MetricSlice) CopyTo(dest MetricSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newMetric((*es.orig)[i]).CopyTo(newMetric((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.Metric, srcLen)
	wrappers := make([]*otlpmetrics.Metric, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newMetric((*es.orig)[i]).CopyTo(newMetric(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new MetricSlice can be initialized:
//   es := NewMetricSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es MetricSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.Metric, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty Metric.
// It returns the newly added Metric.
func (es MetricSlice) AppendEmpty() Metric {
	*es.orig = append(*es.orig, &otlpmetrics.Metric{})
	return es.At(es.Len() - 1)
}

// Sort sorts the Metric elements within MetricSlice given the
// provided less function so that two instances of MetricSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b Metric) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es MetricSlice) Sort(less func(a, b Metric) bool) MetricSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es MetricSlice) MoveAndAppendTo(dest MetricSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es MetricSlice) RemoveIf(f func(Metric) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// Metric represents one metric as a collection of datapoints.
// See Metric definition in OTLP: https://github.com/open-telemetry/opentelemetry-proto/blob/main/opentelemetry/proto/metrics/v1/metrics.proto
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewMetric function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type Metric struct {
	orig *otlpmetrics.Metric
}

func newMetric(orig *otlpmetrics.Metric) Metric {
	return Metric{orig: orig}
}

// NewMetric creates a new empty Metric.
//
// This must be used only in testing code since no "Set" method available.
func NewMetric() Metric {
	return newMetric(&otlpmetrics.Metric{})
}

// Name returns the name associated with this Metric.
func (ms Metric) Name() string {
	return (*ms.orig).Name
}

// SetName replaces the name associated with this Metric.
func (ms Metric) SetName(v string) {
	(*ms.orig).Name = v
}

// Description returns the description associated with this Metric.
func (ms Metric) Description() string {
	return (*ms.orig).Description
}

// SetDescription replaces the description associated with this Metric.
func (ms Metric) SetDescription(v string) {
	(*ms.orig).Description = v
}

// Unit returns the unit associated with this Metric.
func (ms Metric) Unit() string {
	return (*ms.orig).Unit
}

// SetUnit replaces the unit associated with this Metric.
func (ms Metric) SetUnit(v string) {
	(*ms.orig).Unit = v
}

// CopyTo copies all properties from the current struct to the dest.
func (ms Metric) CopyTo(dest Metric) {
	dest.SetName(ms.Name())
	dest.SetDescription(ms.Description())
	dest.SetUnit(ms.Unit())
	copyData(ms.orig, dest.orig)
}

// IntGauge represents the type of a int scalar metric that always exports the "current value" for every data point.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewIntGauge function to create new instances.
// Important: zero-initialized instance is not valid for use.
// Deprecated: Use Gauge instead.
type IntGauge struct {
	orig *otlpmetrics.IntGauge
}

func newIntGauge(orig *otlpmetrics.IntGauge) IntGauge {
	return IntGauge{orig: orig}
}

// NewIntGauge creates a new empty IntGauge.
//
// This must be used only in testing code since no "Set" method available.
func NewIntGauge() IntGauge {
	return newIntGauge(&otlpmetrics.IntGauge{})
}

// DataPoints returns the DataPoints associated with this IntGauge.
func (ms IntGauge) DataPoints() IntDataPointSlice {
	return newIntDataPointSlice(&(*ms.orig).DataPoints)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms IntGauge) CopyTo(dest IntGauge) {
	ms.DataPoints().CopyTo(dest.DataPoints())
}

// Gauge represents the type of a double scalar metric that always exports the "current value" for every data point.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewGauge function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type Gauge struct {
	orig *otlpmetrics.Gauge
}

func newGauge(orig *otlpmetrics.Gauge) Gauge {
	return Gauge{orig: orig}
}

// NewGauge creates a new empty Gauge.
//
// This must be used only in testing code since no "Set" method available.
func NewGauge() Gauge {
	return newGauge(&otlpmetrics.Gauge{})
}

// DataPoints returns the DataPoints associated with this Gauge.
func (ms Gauge) DataPoints() NumberDataPointSlice {
	return newNumberDataPointSlice(&(*ms.orig).DataPoints)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms Gauge) CopyTo(dest Gauge) {
	ms.DataPoints().CopyTo(dest.DataPoints())
}

// IntSum represents the type of a numeric int scalar metric that is calculated as a sum of all reported measurements over a time interval.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewIntSum function to create new instances.
// Important: zero-initialized instance is not valid for use.
// Deprecated: Use Sum instead.
type IntSum struct {
	orig *otlpmetrics.IntSum
}

func newIntSum(orig *otlpmetrics.IntSum) IntSum {
	return IntSum{orig: orig}
}

// NewIntSum creates a new empty IntSum.
//
// This must be used only in testing code since no "Set" method available.
func NewIntSum() IntSum {
	return newIntSum(&otlpmetrics.IntSum{})
}

// AggregationTemporality returns the aggregationtemporality associated with this IntSum.
func (ms IntSum) AggregationTemporality() AggregationTemporality {
	return AggregationTemporality((*ms.orig).AggregationTemporality)
}

// SetAggregationTemporality replaces the aggregationtemporality associated with this IntSum.
func (ms IntSum) SetAggregationTemporality(v AggregationTemporality) {
	(*ms.orig).AggregationTemporality = otlpmetrics.AggregationTemporality(v)
}

// IsMonotonic returns the ismonotonic associated with this IntSum.
func (ms IntSum) IsMonotonic() bool {
	return (*ms.orig).IsMonotonic
}

// SetIsMonotonic replaces the ismonotonic associated with this IntSum.
func (ms IntSum) SetIsMonotonic(v bool) {
	(*ms.orig).IsMonotonic = v
}

// DataPoints returns the DataPoints associated with this IntSum.
func (ms IntSum) DataPoints() IntDataPointSlice {
	return newIntDataPointSlice(&(*ms.orig).DataPoints)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms IntSum) CopyTo(dest IntSum) {
	dest.SetAggregationTemporality(ms.AggregationTemporality())
	dest.SetIsMonotonic(ms.IsMonotonic())
	ms.DataPoints().CopyTo(dest.DataPoints())
}

// Sum represents the type of a numeric double scalar metric that is calculated as a sum of all reported measurements over a time interval.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewSum function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type Sum struct {
	orig *otlpmetrics.Sum
}

func newSum(orig *otlpmetrics.Sum) Sum {
	return Sum{orig: orig}
}

// NewSum creates a new empty Sum.
//
// This must be used only in testing code since no "Set" method available.
func NewSum() Sum {
	return newSum(&otlpmetrics.Sum{})
}

// AggregationTemporality returns the aggregationtemporality associated with this Sum.
func (ms Sum) AggregationTemporality() AggregationTemporality {
	return AggregationTemporality((*ms.orig).AggregationTemporality)
}

// SetAggregationTemporality replaces the aggregationtemporality associated with this Sum.
func (ms Sum) SetAggregationTemporality(v AggregationTemporality) {
	(*ms.orig).AggregationTemporality = otlpmetrics.AggregationTemporality(v)
}

// IsMonotonic returns the ismonotonic associated with this Sum.
func (ms Sum) IsMonotonic() bool {
	return (*ms.orig).IsMonotonic
}

// SetIsMonotonic replaces the ismonotonic associated with this Sum.
func (ms Sum) SetIsMonotonic(v bool) {
	(*ms.orig).IsMonotonic = v
}

// DataPoints returns the DataPoints associated with this Sum.
func (ms Sum) DataPoints() NumberDataPointSlice {
	return newNumberDataPointSlice(&(*ms.orig).DataPoints)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms Sum) CopyTo(dest Sum) {
	dest.SetAggregationTemporality(ms.AggregationTemporality())
	dest.SetIsMonotonic(ms.IsMonotonic())
	ms.DataPoints().CopyTo(dest.DataPoints())
}

// Histogram represents the type of a metric that is calculated by aggregating as a Histogram of all reported measurements over a time interval.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewHistogram function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type Histogram struct {
	orig *otlpmetrics.Histogram
}

func newHistogram(orig *otlpmetrics.Histogram) Histogram {
	return Histogram{orig: orig}
}

// NewHistogram creates a new empty Histogram.
//
// This must be used only in testing code since no "Set" method available.
func NewHistogram() Histogram {
	return newHistogram(&otlpmetrics.Histogram{})
}

// AggregationTemporality returns the aggregationtemporality associated with this Histogram.
func (ms Histogram) AggregationTemporality() AggregationTemporality {
	return AggregationTemporality((*ms.orig).AggregationTemporality)
}

// SetAggregationTemporality replaces the aggregationtemporality associated with this Histogram.
func (ms Histogram) SetAggregationTemporality(v AggregationTemporality) {
	(*ms.orig).AggregationTemporality = otlpmetrics.AggregationTemporality(v)
}

// DataPoints returns the DataPoints associated with this Histogram.
func (ms Histogram) DataPoints() HistogramDataPointSlice {
	return newHistogramDataPointSlice(&(*ms.orig).DataPoints)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms Histogram) CopyTo(dest Histogram) {
	dest.SetAggregationTemporality(ms.AggregationTemporality())
	ms.DataPoints().CopyTo(dest.DataPoints())
}

// Summary represents the type of a metric that is calculated by aggregating as a Summary of all reported double measurements over a time interval.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewSummary function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type Summary struct {
	orig *otlpmetrics.Summary
}

func newSummary(orig *otlpmetrics.Summary) Summary {
	return Summary{orig: orig}
}

// NewSummary creates a new empty Summary.
//
// This must be used only in testing code since no "Set" method available.
func NewSummary() Summary {
	return newSummary(&otlpmetrics.Summary{})
}

// DataPoints returns the DataPoints associated with this Summary.
func (ms Summary) DataPoints() SummaryDataPointSlice {
	return newSummaryDataPointSlice(&(*ms.orig).DataPoints)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms Summary) CopyTo(dest Summary) {
	ms.DataPoints().CopyTo(dest.DataPoints())
}

// IntDataPointSlice logically represents a slice of IntDataPoint.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewIntDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type IntDataPointSlice struct {
	// orig points to the slice otlpmetrics.IntDataPoint field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.IntDataPoint
}

func newIntDataPointSlice(orig *[]*otlpmetrics.IntDataPoint) IntDataPointSlice {
	return IntDataPointSlice{orig}
}

// NewIntDataPointSlice creates a IntDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewIntDataPointSlice() IntDataPointSlice {
	orig := []*otlpmetrics.IntDataPoint(nil)
	return IntDataPointSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewIntDataPointSlice()".
func (es IntDataPointSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es IntDataPointSlice) At(ix int) IntDataPoint {
	return newIntDataPoint((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es IntDataPointSlice) CopyTo(dest IntDataPointSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newIntDataPoint((*es.orig)[i]).CopyTo(newIntDataPoint((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.IntDataPoint, srcLen)
	wrappers := make([]*otlpmetrics.IntDataPoint, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newIntDataPoint((*es.orig)[i]).CopyTo(newIntDataPoint(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new IntDataPointSlice can be initialized:
//   es := NewIntDataPointSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es IntDataPointSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.IntDataPoint, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty IntDataPoint.
// It returns the newly added IntDataPoint.
func (es IntDataPointSlice) AppendEmpty() IntDataPoint {
	*es.orig = append(*es.orig, &otlpmetrics.IntDataPoint{})
	return es.At(es.Len() - 1)
}

// Sort sorts the IntDataPoint elements within IntDataPointSlice given the
// provided less function so that two instances of IntDataPointSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b IntDataPoint) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es IntDataPointSlice) Sort(less func(a, b IntDataPoint) bool) IntDataPointSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es IntDataPointSlice) MoveAndAppendTo(dest IntDataPointSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es IntDataPointSlice) RemoveIf(f func(IntDataPoint) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// IntDataPoint is a single data point in a timeseries that describes the time-varying values of a scalar int metric.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewIntDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
// Deprecated: Use NumberDataPoint instead.
type IntDataPoint struct {
	orig *otlpmetrics.IntDataPoint
}

func newIntDataPoint(orig *otlpmetrics.IntDataPoint) IntDataPoint {
	return IntDataPoint{orig: orig}
}

// NewIntDataPoint creates a new empty IntDataPoint.
//
// This must be used only in testing code since no "Set" method available.
func NewIntDataPoint() IntDataPoint {
	return newIntDataPoint(&otlpmetrics.IntDataPoint{})
}

// LabelsMap returns the Labels associated with this IntDataPoint.
func (ms IntDataPoint) LabelsMap() StringMap {
	return newStringMap(&(*ms.orig).Labels)
}

// StartTimestamp returns the starttimestamp associated with this IntDataPoint.
func (ms IntDataPoint) StartTimestamp() Timestamp {
	return Timestamp((*ms.orig).StartTimeUnixNano)
}

// SetStartTimestamp replaces the starttimestamp associated with this IntDataPoint.
func (ms IntDataPoint) SetStartTimestamp(v Timestamp) {
	(*ms.orig).StartTimeUnixNano = uint64(v)
}

// Timestamp returns the timestamp associated with this IntDataPoint.
func (ms IntDataPoint) Timestamp() Timestamp {
	return Timestamp((*ms.orig).TimeUnixNano)
}

// SetTimestamp replaces the timestamp associated with this IntDataPoint.
func (ms IntDataPoint) SetTimestamp(v Timestamp) {
	(*ms.orig).TimeUnixNano = uint64(v)
}

// Value returns the value associated with this IntDataPoint.
func (ms IntDataPoint) Value() int64 {
	return (*ms.orig).Value
}

// SetValue replaces the value associated with this IntDataPoint.
func (ms IntDataPoint) SetValue(v int64) {
	(*ms.orig).Value = v
}

// CopyTo copies all properties from the current struct to the dest.
func (ms IntDataPoint) CopyTo(dest IntDataPoint) {
	ms.LabelsMap().CopyTo(dest.LabelsMap())
	dest.SetStartTimestamp(ms.StartTimestamp())
	dest.SetTimestamp(ms.Timestamp())
	dest.SetValue(ms.Value())
}

// NumberDataPointSlice logically represents a slice of NumberDataPoint.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewNumberDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type NumberDataPointSlice struct {
	// orig points to the slice otlpmetrics.NumberDataPoint field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.NumberDataPoint
}

func newNumberDataPointSlice(orig *[]*otlpmetrics.NumberDataPoint) NumberDataPointSlice {
	return NumberDataPointSlice{orig}
}

// NewNumberDataPointSlice creates a NumberDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewNumberDataPointSlice() NumberDataPointSlice {
	orig := []*otlpmetrics.NumberDataPoint(nil)
	return NumberDataPointSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewNumberDataPointSlice()".
func (es NumberDataPointSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es NumberDataPointSlice) At(ix int) NumberDataPoint {
	return newNumberDataPoint((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es NumberDataPointSlice) CopyTo(dest NumberDataPointSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newNumberDataPoint((*es.orig)[i]).CopyTo(newNumberDataPoint((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.NumberDataPoint, srcLen)
	wrappers := make([]*otlpmetrics.NumberDataPoint, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newNumberDataPoint((*es.orig)[i]).CopyTo(newNumberDataPoint(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new NumberDataPointSlice can be initialized:
//   es := NewNumberDataPointSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es NumberDataPointSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.NumberDataPoint, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty NumberDataPoint.
// It returns the newly added NumberDataPoint.
func (es NumberDataPointSlice) AppendEmpty() NumberDataPoint {
	*es.orig = append(*es.orig, &otlpmetrics.NumberDataPoint{})
	return es.At(es.Len() - 1)
}

// Sort sorts the NumberDataPoint elements within NumberDataPointSlice given the
// provided less function so that two instances of NumberDataPointSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b NumberDataPoint) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es NumberDataPointSlice) Sort(less func(a, b NumberDataPoint) bool) NumberDataPointSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es NumberDataPointSlice) MoveAndAppendTo(dest NumberDataPointSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es NumberDataPointSlice) RemoveIf(f func(NumberDataPoint) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// NumberDataPoint is a single data point in a timeseries that describes the time-varying value of a number metric.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewNumberDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type NumberDataPoint struct {
	orig *otlpmetrics.NumberDataPoint
}

func newNumberDataPoint(orig *otlpmetrics.NumberDataPoint) NumberDataPoint {
	return NumberDataPoint{orig: orig}
}

// NewNumberDataPoint creates a new empty NumberDataPoint.
//
// This must be used only in testing code since no "Set" method available.
func NewNumberDataPoint() NumberDataPoint {
	return newNumberDataPoint(&otlpmetrics.NumberDataPoint{})
}

// LabelsMap returns the Labels associated with this NumberDataPoint.
func (ms NumberDataPoint) LabelsMap() StringMap {
	return newStringMap(&(*ms.orig).Labels)
}

// StartTimestamp returns the starttimestamp associated with this NumberDataPoint.
func (ms NumberDataPoint) StartTimestamp() Timestamp {
	return Timestamp((*ms.orig).StartTimeUnixNano)
}

// SetStartTimestamp replaces the starttimestamp associated with this NumberDataPoint.
func (ms NumberDataPoint) SetStartTimestamp(v Timestamp) {
	(*ms.orig).StartTimeUnixNano = uint64(v)
}

// Timestamp returns the timestamp associated with this NumberDataPoint.
func (ms NumberDataPoint) Timestamp() Timestamp {
	return Timestamp((*ms.orig).TimeUnixNano)
}

// SetTimestamp replaces the timestamp associated with this NumberDataPoint.
func (ms NumberDataPoint) SetTimestamp(v Timestamp) {
	(*ms.orig).TimeUnixNano = uint64(v)
}

// DoubleVal returns the doubleval associated with this NumberDataPoint.
func (ms NumberDataPoint) DoubleVal() float64 {
	return (*ms.orig).GetAsDouble()
}

// SetDoubleVal replaces the doubleval associated with this NumberDataPoint.
func (ms NumberDataPoint) SetDoubleVal(v float64) {
	(*ms.orig).Value = &otlpmetrics.NumberDataPoint_AsDouble{
		AsDouble: v,
	}
}

// IntVal returns the intval associated with this NumberDataPoint.
func (ms NumberDataPoint) IntVal() int64 {
	return (*ms.orig).GetAsInt()
}

// SetIntVal replaces the intval associated with this NumberDataPoint.
func (ms NumberDataPoint) SetIntVal(v int64) {
	(*ms.orig).Value = &otlpmetrics.NumberDataPoint_AsInt{
		AsInt: v,
	}
}

// Exemplars returns the Exemplars associated with this NumberDataPoint.
func (ms NumberDataPoint) Exemplars() ExemplarSlice {
	return newExemplarSlice(&(*ms.orig).Exemplars)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms NumberDataPoint) CopyTo(dest NumberDataPoint) {
	ms.LabelsMap().CopyTo(dest.LabelsMap())
	dest.SetStartTimestamp(ms.StartTimestamp())
	dest.SetTimestamp(ms.Timestamp())
	switch ms.Type() {
	case MetricValueTypeDouble:
		dest.SetDoubleVal(ms.DoubleVal())
	case MetricValueTypeInt:
		dest.SetIntVal(ms.IntVal())
	}

	ms.Exemplars().CopyTo(dest.Exemplars())
}

// HistogramDataPointSlice logically represents a slice of HistogramDataPoint.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewHistogramDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type HistogramDataPointSlice struct {
	// orig points to the slice otlpmetrics.HistogramDataPoint field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.HistogramDataPoint
}

func newHistogramDataPointSlice(orig *[]*otlpmetrics.HistogramDataPoint) HistogramDataPointSlice {
	return HistogramDataPointSlice{orig}
}

// NewHistogramDataPointSlice creates a HistogramDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewHistogramDataPointSlice() HistogramDataPointSlice {
	orig := []*otlpmetrics.HistogramDataPoint(nil)
	return HistogramDataPointSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewHistogramDataPointSlice()".
func (es HistogramDataPointSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es HistogramDataPointSlice) At(ix int) HistogramDataPoint {
	return newHistogramDataPoint((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es HistogramDataPointSlice) CopyTo(dest HistogramDataPointSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newHistogramDataPoint((*es.orig)[i]).CopyTo(newHistogramDataPoint((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.HistogramDataPoint, srcLen)
	wrappers := make([]*otlpmetrics.HistogramDataPoint, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newHistogramDataPoint((*es.orig)[i]).CopyTo(newHistogramDataPoint(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new HistogramDataPointSlice can be initialized:
//   es := NewHistogramDataPointSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es HistogramDataPointSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.HistogramDataPoint, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty HistogramDataPoint.
// It returns the newly added HistogramDataPoint.
func (es HistogramDataPointSlice) AppendEmpty() HistogramDataPoint {
	*es.orig = append(*es.orig, &otlpmetrics.HistogramDataPoint{})
	return es.At(es.Len() - 1)
}

// Sort sorts the HistogramDataPoint elements within HistogramDataPointSlice given the
// provided less function so that two instances of HistogramDataPointSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b HistogramDataPoint) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es HistogramDataPointSlice) Sort(less func(a, b HistogramDataPoint) bool) HistogramDataPointSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es HistogramDataPointSlice) MoveAndAppendTo(dest HistogramDataPointSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es HistogramDataPointSlice) RemoveIf(f func(HistogramDataPoint) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// HistogramDataPoint is a single data point in a timeseries that describes the time-varying values of a Histogram of values.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewHistogramDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type HistogramDataPoint struct {
	orig *otlpmetrics.HistogramDataPoint
}

func newHistogramDataPoint(orig *otlpmetrics.HistogramDataPoint) HistogramDataPoint {
	return HistogramDataPoint{orig: orig}
}

// NewHistogramDataPoint creates a new empty HistogramDataPoint.
//
// This must be used only in testing code since no "Set" method available.
func NewHistogramDataPoint() HistogramDataPoint {
	return newHistogramDataPoint(&otlpmetrics.HistogramDataPoint{})
}

// LabelsMap returns the Labels associated with this HistogramDataPoint.
func (ms HistogramDataPoint) LabelsMap() StringMap {
	return newStringMap(&(*ms.orig).Labels)
}

// StartTimestamp returns the starttimestamp associated with this HistogramDataPoint.
func (ms HistogramDataPoint) StartTimestamp() Timestamp {
	return Timestamp((*ms.orig).StartTimeUnixNano)
}

// SetStartTimestamp replaces the starttimestamp associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetStartTimestamp(v Timestamp) {
	(*ms.orig).StartTimeUnixNano = uint64(v)
}

// Timestamp returns the timestamp associated with this HistogramDataPoint.
func (ms HistogramDataPoint) Timestamp() Timestamp {
	return Timestamp((*ms.orig).TimeUnixNano)
}

// SetTimestamp replaces the timestamp associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetTimestamp(v Timestamp) {
	(*ms.orig).TimeUnixNano = uint64(v)
}

// Count returns the count associated with this HistogramDataPoint.
func (ms HistogramDataPoint) Count() uint64 {
	return (*ms.orig).Count
}

// SetCount replaces the count associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetCount(v uint64) {
	(*ms.orig).Count = v
}

// Sum returns the sum associated with this HistogramDataPoint.
func (ms HistogramDataPoint) Sum() float64 {
	return (*ms.orig).Sum
}

// SetSum replaces the sum associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetSum(v float64) {
	(*ms.orig).Sum = v
}

// BucketCounts returns the bucketcounts associated with this HistogramDataPoint.
func (ms HistogramDataPoint) BucketCounts() []uint64 {
	return (*ms.orig).BucketCounts
}

// SetBucketCounts replaces the bucketcounts associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetBucketCounts(v []uint64) {
	(*ms.orig).BucketCounts = v
}

// ExplicitBounds returns the explicitbounds associated with this HistogramDataPoint.
func (ms HistogramDataPoint) ExplicitBounds() []float64 {
	return (*ms.orig).ExplicitBounds
}

// SetExplicitBounds replaces the explicitbounds associated with this HistogramDataPoint.
func (ms HistogramDataPoint) SetExplicitBounds(v []float64) {
	(*ms.orig).ExplicitBounds = v
}

// Exemplars returns the Exemplars associated with this HistogramDataPoint.
func (ms HistogramDataPoint) Exemplars() ExemplarSlice {
	return newExemplarSlice(&(*ms.orig).Exemplars)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms HistogramDataPoint) CopyTo(dest HistogramDataPoint) {
	ms.LabelsMap().CopyTo(dest.LabelsMap())
	dest.SetStartTimestamp(ms.StartTimestamp())
	dest.SetTimestamp(ms.Timestamp())
	dest.SetCount(ms.Count())
	dest.SetSum(ms.Sum())
	dest.SetBucketCounts(ms.BucketCounts())
	dest.SetExplicitBounds(ms.ExplicitBounds())
	ms.Exemplars().CopyTo(dest.Exemplars())
}

// SummaryDataPointSlice logically represents a slice of SummaryDataPoint.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewSummaryDataPointSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type SummaryDataPointSlice struct {
	// orig points to the slice otlpmetrics.SummaryDataPoint field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.SummaryDataPoint
}

func newSummaryDataPointSlice(orig *[]*otlpmetrics.SummaryDataPoint) SummaryDataPointSlice {
	return SummaryDataPointSlice{orig}
}

// NewSummaryDataPointSlice creates a SummaryDataPointSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewSummaryDataPointSlice() SummaryDataPointSlice {
	orig := []*otlpmetrics.SummaryDataPoint(nil)
	return SummaryDataPointSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewSummaryDataPointSlice()".
func (es SummaryDataPointSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es SummaryDataPointSlice) At(ix int) SummaryDataPoint {
	return newSummaryDataPoint((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es SummaryDataPointSlice) CopyTo(dest SummaryDataPointSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newSummaryDataPoint((*es.orig)[i]).CopyTo(newSummaryDataPoint((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.SummaryDataPoint, srcLen)
	wrappers := make([]*otlpmetrics.SummaryDataPoint, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newSummaryDataPoint((*es.orig)[i]).CopyTo(newSummaryDataPoint(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new SummaryDataPointSlice can be initialized:
//   es := NewSummaryDataPointSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es SummaryDataPointSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.SummaryDataPoint, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty SummaryDataPoint.
// It returns the newly added SummaryDataPoint.
func (es SummaryDataPointSlice) AppendEmpty() SummaryDataPoint {
	*es.orig = append(*es.orig, &otlpmetrics.SummaryDataPoint{})
	return es.At(es.Len() - 1)
}

// Sort sorts the SummaryDataPoint elements within SummaryDataPointSlice given the
// provided less function so that two instances of SummaryDataPointSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b SummaryDataPoint) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es SummaryDataPointSlice) Sort(less func(a, b SummaryDataPoint) bool) SummaryDataPointSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es SummaryDataPointSlice) MoveAndAppendTo(dest SummaryDataPointSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es SummaryDataPointSlice) RemoveIf(f func(SummaryDataPoint) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// SummaryDataPoint is a single data point in a timeseries that describes the time-varying values of a Summary of double values.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewSummaryDataPoint function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type SummaryDataPoint struct {
	orig *otlpmetrics.SummaryDataPoint
}

func newSummaryDataPoint(orig *otlpmetrics.SummaryDataPoint) SummaryDataPoint {
	return SummaryDataPoint{orig: orig}
}

// NewSummaryDataPoint creates a new empty SummaryDataPoint.
//
// This must be used only in testing code since no "Set" method available.
func NewSummaryDataPoint() SummaryDataPoint {
	return newSummaryDataPoint(&otlpmetrics.SummaryDataPoint{})
}

// LabelsMap returns the Labels associated with this SummaryDataPoint.
func (ms SummaryDataPoint) LabelsMap() StringMap {
	return newStringMap(&(*ms.orig).Labels)
}

// StartTimestamp returns the starttimestamp associated with this SummaryDataPoint.
func (ms SummaryDataPoint) StartTimestamp() Timestamp {
	return Timestamp((*ms.orig).StartTimeUnixNano)
}

// SetStartTimestamp replaces the starttimestamp associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetStartTimestamp(v Timestamp) {
	(*ms.orig).StartTimeUnixNano = uint64(v)
}

// Timestamp returns the timestamp associated with this SummaryDataPoint.
func (ms SummaryDataPoint) Timestamp() Timestamp {
	return Timestamp((*ms.orig).TimeUnixNano)
}

// SetTimestamp replaces the timestamp associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetTimestamp(v Timestamp) {
	(*ms.orig).TimeUnixNano = uint64(v)
}

// Count returns the count associated with this SummaryDataPoint.
func (ms SummaryDataPoint) Count() uint64 {
	return (*ms.orig).Count
}

// SetCount replaces the count associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetCount(v uint64) {
	(*ms.orig).Count = v
}

// Sum returns the sum associated with this SummaryDataPoint.
func (ms SummaryDataPoint) Sum() float64 {
	return (*ms.orig).Sum
}

// SetSum replaces the sum associated with this SummaryDataPoint.
func (ms SummaryDataPoint) SetSum(v float64) {
	(*ms.orig).Sum = v
}

// QuantileValues returns the QuantileValues associated with this SummaryDataPoint.
func (ms SummaryDataPoint) QuantileValues() ValueAtQuantileSlice {
	return newValueAtQuantileSlice(&(*ms.orig).QuantileValues)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms SummaryDataPoint) CopyTo(dest SummaryDataPoint) {
	ms.LabelsMap().CopyTo(dest.LabelsMap())
	dest.SetStartTimestamp(ms.StartTimestamp())
	dest.SetTimestamp(ms.Timestamp())
	dest.SetCount(ms.Count())
	dest.SetSum(ms.Sum())
	ms.QuantileValues().CopyTo(dest.QuantileValues())
}

// ValueAtQuantileSlice logically represents a slice of ValueAtQuantile.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewValueAtQuantileSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ValueAtQuantileSlice struct {
	// orig points to the slice otlpmetrics.SummaryDataPoint_ValueAtQuantile field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile
}

func newValueAtQuantileSlice(orig *[]*otlpmetrics.SummaryDataPoint_ValueAtQuantile) ValueAtQuantileSlice {
	return ValueAtQuantileSlice{orig}
}

// NewValueAtQuantileSlice creates a ValueAtQuantileSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewValueAtQuantileSlice() ValueAtQuantileSlice {
	orig := []*otlpmetrics.SummaryDataPoint_ValueAtQuantile(nil)
	return ValueAtQuantileSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewValueAtQuantileSlice()".
func (es ValueAtQuantileSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es ValueAtQuantileSlice) At(ix int) ValueAtQuantile {
	return newValueAtQuantile((*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es ValueAtQuantileSlice) CopyTo(dest ValueAtQuantileSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
		for i := range *es.orig {
			newValueAtQuantile((*es.orig)[i]).CopyTo(newValueAtQuantile((*dest.orig)[i]))
		}
		return
	}
	origs := make([]otlpmetrics.SummaryDataPoint_ValueAtQuantile, srcLen)
	wrappers := make([]*otlpmetrics.SummaryDataPoint_ValueAtQuantile, srcLen)
	for i := range *es.orig {
		wrappers[i] = &origs[i]
		newValueAtQuantile((*es.orig)[i]).CopyTo(newValueAtQuantile(wrappers[i]))
	}
	*dest.orig = wrappers
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new ValueAtQuantileSlice can be initialized:
//   es := NewValueAtQuantileSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es ValueAtQuantileSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]*otlpmetrics.SummaryDataPoint_ValueAtQuantile, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty ValueAtQuantile.
// It returns the newly added ValueAtQuantile.
func (es ValueAtQuantileSlice) AppendEmpty() ValueAtQuantile {
	*es.orig = append(*es.orig, &otlpmetrics.SummaryDataPoint_ValueAtQuantile{})
	return es.At(es.Len() - 1)
}

// Sort sorts the ValueAtQuantile elements within ValueAtQuantileSlice given the
// provided less function so that two instances of ValueAtQuantileSlice
// can be compared.
//
// Returns the same instance to allow nicer code like:
//   lessFunc := func(a, b ValueAtQuantile) bool {
//     return a.Name() < b.Name() // choose any comparison here
//   }
//   assert.EqualValues(t, expected.Sort(lessFunc), actual.Sort(lessFunc))
func (es ValueAtQuantileSlice) Sort(less func(a, b ValueAtQuantile) bool) ValueAtQuantileSlice {
	sort.SliceStable(*es.orig, func(i, j int) bool { return less(es.At(i), es.At(j)) })
	return es
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ValueAtQuantileSlice) MoveAndAppendTo(dest ValueAtQuantileSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ValueAtQuantileSlice) RemoveIf(f func(ValueAtQuantile) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// ValueAtQuantile is a quantile value within a Summary data point.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewValueAtQuantile function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type ValueAtQuantile struct {
	orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile
}

func newValueAtQuantile(orig *otlpmetrics.SummaryDataPoint_ValueAtQuantile) ValueAtQuantile {
	return ValueAtQuantile{orig: orig}
}

// NewValueAtQuantile creates a new empty ValueAtQuantile.
//
// This must be used only in testing code since no "Set" method available.
func NewValueAtQuantile() ValueAtQuantile {
	return newValueAtQuantile(&otlpmetrics.SummaryDataPoint_ValueAtQuantile{})
}

// Quantile returns the quantile associated with this ValueAtQuantile.
func (ms ValueAtQuantile) Quantile() float64 {
	return (*ms.orig).Quantile
}

// SetQuantile replaces the quantile associated with this ValueAtQuantile.
func (ms ValueAtQuantile) SetQuantile(v float64) {
	(*ms.orig).Quantile = v
}

// Value returns the value associated with this ValueAtQuantile.
func (ms ValueAtQuantile) Value() float64 {
	return (*ms.orig).Value
}

// SetValue replaces the value associated with this ValueAtQuantile.
func (ms ValueAtQuantile) SetValue(v float64) {
	(*ms.orig).Value = v
}

// CopyTo copies all properties from the current struct to the dest.
func (ms ValueAtQuantile) CopyTo(dest ValueAtQuantile) {
	dest.SetQuantile(ms.Quantile())
	dest.SetValue(ms.Value())
}

// ExemplarSlice logically represents a slice of Exemplar.
//
// This is a reference type. If passed by value and callee modifies it, the
// caller will see the modification.
//
// Must use NewExemplarSlice function to create new instances.
// Important: zero-initialized instance is not valid for use.
type ExemplarSlice struct {
	// orig points to the slice otlpmetrics.Exemplar field contained somewhere else.
	// We use pointer-to-slice to be able to modify it in functions like EnsureCapacity.
	orig *[]otlpmetrics.Exemplar
}

func newExemplarSlice(orig *[]otlpmetrics.Exemplar) ExemplarSlice {
	return ExemplarSlice{orig}
}

// NewExemplarSlice creates a ExemplarSlice with 0 elements.
// Can use "EnsureCapacity" to initialize with a given capacity.
func NewExemplarSlice() ExemplarSlice {
	orig := []otlpmetrics.Exemplar(nil)
	return ExemplarSlice{&orig}
}

// Len returns the number of elements in the slice.
//
// Returns "0" for a newly instance created with "NewExemplarSlice()".
func (es ExemplarSlice) Len() int {
	return len(*es.orig)
}

// At returns the element at the given index.
//
// This function is used mostly for iterating over all the values in the slice:
//   for i := 0; i < es.Len(); i++ {
//       e := es.At(i)
//       ... // Do something with the element
//   }
func (es ExemplarSlice) At(ix int) Exemplar {
	return newExemplar(&(*es.orig)[ix])
}

// CopyTo copies all elements from the current slice to the dest.
func (es ExemplarSlice) CopyTo(dest ExemplarSlice) {
	srcLen := es.Len()
	destCap := cap(*dest.orig)
	if srcLen <= destCap {
		(*dest.orig) = (*dest.orig)[:srcLen:destCap]
	} else {
		(*dest.orig) = make([]otlpmetrics.Exemplar, srcLen)
	}

	for i := range *es.orig {
		newExemplar(&(*es.orig)[i]).CopyTo(newExemplar(&(*dest.orig)[i]))
	}
}

// EnsureCapacity is an operation that ensures the slice has at least the specified capacity.
// 1. If the newCap <= cap then no change in capacity.
// 2. If the newCap > cap then the slice capacity will be expanded to equal newCap.
//
// Here is how a new ExemplarSlice can be initialized:
//   es := NewExemplarSlice()
//   es.EnsureCapacity(4)
//   for i := 0; i < 4; i++ {
//       e := es.AppendEmpty()
//       // Here should set all the values for e.
//   }
func (es ExemplarSlice) EnsureCapacity(newCap int) {
	oldCap := cap(*es.orig)
	if newCap <= oldCap {
		return
	}

	newOrig := make([]otlpmetrics.Exemplar, len(*es.orig), newCap)
	copy(newOrig, *es.orig)
	*es.orig = newOrig
}

// AppendEmpty will append to the end of the slice an empty Exemplar.
// It returns the newly added Exemplar.
func (es ExemplarSlice) AppendEmpty() Exemplar {
	*es.orig = append(*es.orig, otlpmetrics.Exemplar{})
	return es.At(es.Len() - 1)
}

// MoveAndAppendTo moves all elements from the current slice and appends them to the dest.
// The current slice will be cleared.
func (es ExemplarSlice) MoveAndAppendTo(dest ExemplarSlice) {
	if *dest.orig == nil {
		// We can simply move the entire vector and avoid any allocations.
		*dest.orig = *es.orig
	} else {
		*dest.orig = append(*dest.orig, *es.orig...)
	}
	*es.orig = nil
}

// RemoveIf calls f sequentially for each element present in the slice.
// If f returns true, the element is removed from the slice.
func (es ExemplarSlice) RemoveIf(f func(Exemplar) bool) {
	newLen := 0
	for i := 0; i < len(*es.orig); i++ {
		if f(es.At(i)) {
			continue
		}
		if newLen == i {
			// Nothing to move, element is at the right place.
			newLen++
			continue
		}
		(*es.orig)[newLen] = (*es.orig)[i]
		newLen++
	}
	// TODO: Prevent memory leak by erasing truncated values.
	*es.orig = (*es.orig)[:newLen]
}

// Exemplar is a sample input double measurement.
//
// Exemplars also hold information about the environment when the measurement was recorded,
// for example the span and trace ID of the active span when the exemplar was recorded.
//
// This is a reference type, if passed by value and callee modifies it the
// caller will see the modification.
//
// Must use NewExemplar function to create new instances.
// Important: zero-initialized instance is not valid for use.
//
type Exemplar struct {
	orig *otlpmetrics.Exemplar
}

func newExemplar(orig *otlpmetrics.Exemplar) Exemplar {
	return Exemplar{orig: orig}
}

// NewExemplar creates a new empty Exemplar.
//
// This must be used only in testing code since no "Set" method available.
func NewExemplar() Exemplar {
	return newExemplar(&otlpmetrics.Exemplar{})
}

// Timestamp returns the timestamp associated with this Exemplar.
func (ms Exemplar) Timestamp() Timestamp {
	return Timestamp((*ms.orig).TimeUnixNano)
}

// SetTimestamp replaces the timestamp associated with this Exemplar.
func (ms Exemplar) SetTimestamp(v Timestamp) {
	(*ms.orig).TimeUnixNano = uint64(v)
}

// DoubleVal returns the doubleval associated with this Exemplar.
func (ms Exemplar) DoubleVal() float64 {
	return (*ms.orig).GetAsDouble()
}

// SetDoubleVal replaces the doubleval associated with this Exemplar.
func (ms Exemplar) SetDoubleVal(v float64) {
	(*ms.orig).Value = &otlpmetrics.Exemplar_AsDouble{
		AsDouble: v,
	}
}

// IntVal returns the intval associated with this Exemplar.
func (ms Exemplar) IntVal() int64 {
	return (*ms.orig).GetAsInt()
}

// SetIntVal replaces the intval associated with this Exemplar.
func (ms Exemplar) SetIntVal(v int64) {
	(*ms.orig).Value = &otlpmetrics.Exemplar_AsInt{
		AsInt: v,
	}
}

// FilteredLabels returns the FilteredLabels associated with this Exemplar.
func (ms Exemplar) FilteredLabels() StringMap {
	return newStringMap(&(*ms.orig).FilteredLabels)
}

// CopyTo copies all properties from the current struct to the dest.
func (ms Exemplar) CopyTo(dest Exemplar) {
	dest.SetTimestamp(ms.Timestamp())
	switch ms.Type() {
	case MetricValueTypeDouble:
		dest.SetDoubleVal(ms.DoubleVal())
	case MetricValueTypeInt:
		dest.SetIntVal(ms.IntVal())
	}

	ms.FilteredLabels().CopyTo(dest.FilteredLabels())
}
