/*
 * Copyright (c) 2018 - present.  Boling Consulting Solutions (bcsw.net)
 * Copyright 2020-present Open Networking Foundation
 *
 * 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.
 */
/*
 * NOTE: This file was generated, manual edits will be overwritten!
 *
 * Generated by 'goCodeGenerator.py':
 *              https://github.com/cboling/OMCI-parser/README.md
 */

package generated

import (
	"errors"
)

// Custom Go Error messages for relaxed decode error signaling.
//
//   gopacket does not provide a way to easily perform relaxed decoding calls
//   during the 'DecodeFromBytes' decoding of a layer. It does allow for an error
//   code returned and this will be used to allow for relaxed decoding. If a
//   particular message type decode can be relaxed, process it as relax and
//   return an error derived from the RelaxedDecodeError below and check for
//   it as appropriate.

// IRelaxedDecodeError provides a base interface that can be used to derive
// other decode specific errors that can be relaxed at the application's
// discretion
type IRelaxedDecodeError interface {
	// Error interface, so if relaxed decode is not supported, this behaves as
	// a normal error
	Error() string
	GetError() error

	////////////////////////////////
	// Relaxed error specific

	// GetContents returns the octet payload specific to the error if it can be
	// determined. Derived relaxed decode errors may provide more specific control
	// and information
	GetContents() []byte
}

type RelaxedDecodeError struct {
	err      string
	Contents []byte
}

func (e *RelaxedDecodeError) GetError() error {
	return errors.New(e.err)
}

func (e *RelaxedDecodeError) Error() string {
	return e.err
}

func (e *RelaxedDecodeError) GetContents() []byte {
	return e.Contents
}

// UnknownAttributeDecodeError is used to convey unknown attributes found in
// a received packet undergoing decode. These will always be trailing attributes
// in packets and are often due to:
//     o New versions of ITU G.988 being issued with an existing ME getting new
//       attributes,
//
//     o An error in the code generated classes in this library where one or more
//       attributes were missed, or
//
//     o An error in the OLT/ONU that serialized the message
type UnknownAttributeDecodeError struct {
	RelaxedDecodeError
	AttributeMask uint16

	EntityClass    ClassID // Set by first level handler of the error
	EntityInstance uint16  // Set by first level handler of the error
}

func NewUnknownAttributeDecodeError(msg string, mask uint16, contents []byte) *UnknownAttributeDecodeError {
	err := &UnknownAttributeDecodeError{
		RelaxedDecodeError: RelaxedDecodeError{
			err: msg,
		},
		AttributeMask: mask,
	}
	if contents != nil {
		err.Contents = make([]byte, len(contents))
		copy(err.Contents, contents)
	}
	return err
}
