// Code generated by protoc-gen-validate. DO NOT EDIT.
// source: go.chromium.org/luci/cv/internal/tryjob/task.proto

package tryjob

import (
	"bytes"
	"errors"
	"fmt"
	"net"
	"net/mail"
	"net/url"
	"regexp"
	"sort"
	"strings"
	"time"
	"unicode/utf8"

	"google.golang.org/protobuf/types/known/anypb"
)

// ensure the imports are used
var (
	_ = bytes.MinRead
	_ = errors.New("")
	_ = fmt.Print
	_ = utf8.UTFMax
	_ = (*regexp.Regexp)(nil)
	_ = (*strings.Reader)(nil)
	_ = net.IPv4len
	_ = time.Duration(0)
	_ = (*url.URL)(nil)
	_ = (*mail.Address)(nil)
	_ = anypb.Any{}
	_ = sort.Sort
)

// Validate checks the field values on UpdateTryjobTask with the rules defined
// in the proto definition for this message. If any rules are violated, the
// first error encountered is returned, or nil if there are no violations.
func (m *UpdateTryjobTask) Validate() error {
	return m.validate(false)
}

// ValidateAll checks the field values on UpdateTryjobTask with the rules
// defined in the proto definition for this message. If any rules are
// violated, the result is a list of violation errors wrapped in
// UpdateTryjobTaskMultiError, or nil if none found.
func (m *UpdateTryjobTask) ValidateAll() error {
	return m.validate(true)
}

func (m *UpdateTryjobTask) validate(all bool) error {
	if m == nil {
		return nil
	}

	var errors []error

	// no validation rules for Id

	// no validation rules for ExternalId

	if len(errors) > 0 {
		return UpdateTryjobTaskMultiError(errors)
	}

	return nil
}

// UpdateTryjobTaskMultiError is an error wrapping multiple validation errors
// returned by UpdateTryjobTask.ValidateAll() if the designated constraints
// aren't met.
type UpdateTryjobTaskMultiError []error

// Error returns a concatenation of all the error messages it wraps.
func (m UpdateTryjobTaskMultiError) Error() string {
	var msgs []string
	for _, err := range m {
		msgs = append(msgs, err.Error())
	}
	return strings.Join(msgs, "; ")
}

// AllErrors returns a list of validation violation errors.
func (m UpdateTryjobTaskMultiError) AllErrors() []error { return m }

// UpdateTryjobTaskValidationError is the validation error returned by
// UpdateTryjobTask.Validate if the designated constraints aren't met.
type UpdateTryjobTaskValidationError struct {
	field  string
	reason string
	cause  error
	key    bool
}

// Field function returns field value.
func (e UpdateTryjobTaskValidationError) Field() string { return e.field }

// Reason function returns reason value.
func (e UpdateTryjobTaskValidationError) Reason() string { return e.reason }

// Cause function returns cause value.
func (e UpdateTryjobTaskValidationError) Cause() error { return e.cause }

// Key function returns key value.
func (e UpdateTryjobTaskValidationError) Key() bool { return e.key }

// ErrorName returns error name.
func (e UpdateTryjobTaskValidationError) ErrorName() string { return "UpdateTryjobTaskValidationError" }

// Error satisfies the builtin error interface
func (e UpdateTryjobTaskValidationError) Error() string {
	cause := ""
	if e.cause != nil {
		cause = fmt.Sprintf(" | caused by: %v", e.cause)
	}

	key := ""
	if e.key {
		key = "key for "
	}

	return fmt.Sprintf(
		"invalid %sUpdateTryjobTask.%s: %s%s",
		key,
		e.field,
		e.reason,
		cause)
}

var _ error = UpdateTryjobTaskValidationError{}

var _ interface {
	Field() string
	Reason() string
	Key() bool
	Cause() error
	ErrorName() string
} = UpdateTryjobTaskValidationError{}

// Validate checks the field values on CancelStaleTryjobsTask with the rules
// defined in the proto definition for this message. If any rules are
// violated, the first error encountered is returned, or nil if there are no violations.
func (m *CancelStaleTryjobsTask) Validate() error {
	return m.validate(false)
}

// ValidateAll checks the field values on CancelStaleTryjobsTask with the rules
// defined in the proto definition for this message. If any rules are
// violated, the result is a list of violation errors wrapped in
// CancelStaleTryjobsTaskMultiError, or nil if none found.
func (m *CancelStaleTryjobsTask) ValidateAll() error {
	return m.validate(true)
}

func (m *CancelStaleTryjobsTask) validate(all bool) error {
	if m == nil {
		return nil
	}

	var errors []error

	// no validation rules for Clid

	// no validation rules for PreviousMinEquivPatchset

	// no validation rules for CurrentMinEquivPatchset

	if len(errors) > 0 {
		return CancelStaleTryjobsTaskMultiError(errors)
	}

	return nil
}

// CancelStaleTryjobsTaskMultiError is an error wrapping multiple validation
// errors returned by CancelStaleTryjobsTask.ValidateAll() if the designated
// constraints aren't met.
type CancelStaleTryjobsTaskMultiError []error

// Error returns a concatenation of all the error messages it wraps.
func (m CancelStaleTryjobsTaskMultiError) Error() string {
	var msgs []string
	for _, err := range m {
		msgs = append(msgs, err.Error())
	}
	return strings.Join(msgs, "; ")
}

// AllErrors returns a list of validation violation errors.
func (m CancelStaleTryjobsTaskMultiError) AllErrors() []error { return m }

// CancelStaleTryjobsTaskValidationError is the validation error returned by
// CancelStaleTryjobsTask.Validate if the designated constraints aren't met.
type CancelStaleTryjobsTaskValidationError struct {
	field  string
	reason string
	cause  error
	key    bool
}

// Field function returns field value.
func (e CancelStaleTryjobsTaskValidationError) Field() string { return e.field }

// Reason function returns reason value.
func (e CancelStaleTryjobsTaskValidationError) Reason() string { return e.reason }

// Cause function returns cause value.
func (e CancelStaleTryjobsTaskValidationError) Cause() error { return e.cause }

// Key function returns key value.
func (e CancelStaleTryjobsTaskValidationError) Key() bool { return e.key }

// ErrorName returns error name.
func (e CancelStaleTryjobsTaskValidationError) ErrorName() string {
	return "CancelStaleTryjobsTaskValidationError"
}

// Error satisfies the builtin error interface
func (e CancelStaleTryjobsTaskValidationError) Error() string {
	cause := ""
	if e.cause != nil {
		cause = fmt.Sprintf(" | caused by: %v", e.cause)
	}

	key := ""
	if e.key {
		key = "key for "
	}

	return fmt.Sprintf(
		"invalid %sCancelStaleTryjobsTask.%s: %s%s",
		key,
		e.field,
		e.reason,
		cause)
}

var _ error = CancelStaleTryjobsTaskValidationError{}

var _ interface {
	Field() string
	Reason() string
	Key() bool
	Cause() error
	ErrorName() string
} = CancelStaleTryjobsTaskValidationError{}

// Validate checks the field values on ExecuteTryjobsPayload with the rules
// defined in the proto definition for this message. If any rules are
// violated, the first error encountered is returned, or nil if there are no violations.
func (m *ExecuteTryjobsPayload) Validate() error {
	return m.validate(false)
}

// ValidateAll checks the field values on ExecuteTryjobsPayload with the rules
// defined in the proto definition for this message. If any rules are
// violated, the result is a list of violation errors wrapped in
// ExecuteTryjobsPayloadMultiError, or nil if none found.
func (m *ExecuteTryjobsPayload) ValidateAll() error {
	return m.validate(true)
}

func (m *ExecuteTryjobsPayload) validate(all bool) error {
	if m == nil {
		return nil
	}

	var errors []error

	// no validation rules for RequirementChanged

	if len(errors) > 0 {
		return ExecuteTryjobsPayloadMultiError(errors)
	}

	return nil
}

// ExecuteTryjobsPayloadMultiError is an error wrapping multiple validation
// errors returned by ExecuteTryjobsPayload.ValidateAll() if the designated
// constraints aren't met.
type ExecuteTryjobsPayloadMultiError []error

// Error returns a concatenation of all the error messages it wraps.
func (m ExecuteTryjobsPayloadMultiError) Error() string {
	var msgs []string
	for _, err := range m {
		msgs = append(msgs, err.Error())
	}
	return strings.Join(msgs, "; ")
}

// AllErrors returns a list of validation violation errors.
func (m ExecuteTryjobsPayloadMultiError) AllErrors() []error { return m }

// ExecuteTryjobsPayloadValidationError is the validation error returned by
// ExecuteTryjobsPayload.Validate if the designated constraints aren't met.
type ExecuteTryjobsPayloadValidationError struct {
	field  string
	reason string
	cause  error
	key    bool
}

// Field function returns field value.
func (e ExecuteTryjobsPayloadValidationError) Field() string { return e.field }

// Reason function returns reason value.
func (e ExecuteTryjobsPayloadValidationError) Reason() string { return e.reason }

// Cause function returns cause value.
func (e ExecuteTryjobsPayloadValidationError) Cause() error { return e.cause }

// Key function returns key value.
func (e ExecuteTryjobsPayloadValidationError) Key() bool { return e.key }

// ErrorName returns error name.
func (e ExecuteTryjobsPayloadValidationError) ErrorName() string {
	return "ExecuteTryjobsPayloadValidationError"
}

// Error satisfies the builtin error interface
func (e ExecuteTryjobsPayloadValidationError) Error() string {
	cause := ""
	if e.cause != nil {
		cause = fmt.Sprintf(" | caused by: %v", e.cause)
	}

	key := ""
	if e.key {
		key = "key for "
	}

	return fmt.Sprintf(
		"invalid %sExecuteTryjobsPayload.%s: %s%s",
		key,
		e.field,
		e.reason,
		cause)
}

var _ error = ExecuteTryjobsPayloadValidationError{}

var _ interface {
	Field() string
	Reason() string
	Key() bool
	Cause() error
	ErrorName() string
} = ExecuteTryjobsPayloadValidationError{}

// Validate checks the field values on ExecuteTryjobsResult with the rules
// defined in the proto definition for this message. If any rules are
// violated, the first error encountered is returned, or nil if there are no violations.
func (m *ExecuteTryjobsResult) Validate() error {
	return m.validate(false)
}

// ValidateAll checks the field values on ExecuteTryjobsResult with the rules
// defined in the proto definition for this message. If any rules are
// violated, the result is a list of violation errors wrapped in
// ExecuteTryjobsResultMultiError, or nil if none found.
func (m *ExecuteTryjobsResult) ValidateAll() error {
	return m.validate(true)
}

func (m *ExecuteTryjobsResult) validate(all bool) error {
	if m == nil {
		return nil
	}

	var errors []error

	if len(errors) > 0 {
		return ExecuteTryjobsResultMultiError(errors)
	}

	return nil
}

// ExecuteTryjobsResultMultiError is an error wrapping multiple validation
// errors returned by ExecuteTryjobsResult.ValidateAll() if the designated
// constraints aren't met.
type ExecuteTryjobsResultMultiError []error

// Error returns a concatenation of all the error messages it wraps.
func (m ExecuteTryjobsResultMultiError) Error() string {
	var msgs []string
	for _, err := range m {
		msgs = append(msgs, err.Error())
	}
	return strings.Join(msgs, "; ")
}

// AllErrors returns a list of validation violation errors.
func (m ExecuteTryjobsResultMultiError) AllErrors() []error { return m }

// ExecuteTryjobsResultValidationError is the validation error returned by
// ExecuteTryjobsResult.Validate if the designated constraints aren't met.
type ExecuteTryjobsResultValidationError struct {
	field  string
	reason string
	cause  error
	key    bool
}

// Field function returns field value.
func (e ExecuteTryjobsResultValidationError) Field() string { return e.field }

// Reason function returns reason value.
func (e ExecuteTryjobsResultValidationError) Reason() string { return e.reason }

// Cause function returns cause value.
func (e ExecuteTryjobsResultValidationError) Cause() error { return e.cause }

// Key function returns key value.
func (e ExecuteTryjobsResultValidationError) Key() bool { return e.key }

// ErrorName returns error name.
func (e ExecuteTryjobsResultValidationError) ErrorName() string {
	return "ExecuteTryjobsResultValidationError"
}

// Error satisfies the builtin error interface
func (e ExecuteTryjobsResultValidationError) Error() string {
	cause := ""
	if e.cause != nil {
		cause = fmt.Sprintf(" | caused by: %v", e.cause)
	}

	key := ""
	if e.key {
		key = "key for "
	}

	return fmt.Sprintf(
		"invalid %sExecuteTryjobsResult.%s: %s%s",
		key,
		e.field,
		e.reason,
		cause)
}

var _ error = ExecuteTryjobsResultValidationError{}

var _ interface {
	Field() string
	Reason() string
	Key() bool
	Cause() error
	ErrorName() string
} = ExecuteTryjobsResultValidationError{}
