<?php
# Generated by the protocol buffer compiler.  DO NOT EDIT!
# NO CHECKED-IN PROTOBUF GENCODE
# source: google/protobuf/descriptor.proto

namespace Google\Protobuf\Internal;

use Google\Protobuf\Internal\GPBType;
use Google\Protobuf\Internal\GPBWire;
use Google\Protobuf\Internal\InputStream;
use Google\Protobuf\Internal\GPBUtil;
use Google\Protobuf\RepeatedField;

/**
 * Generated from protobuf message <code>google.protobuf.ExtensionRangeOptions</code>
 */
class ExtensionRangeOptions extends \Google\Protobuf\Internal\Message
{
    /**
     * The parser stores options it doesn't recognize here. See above.
     *
     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
     */
    private $uninterpreted_option;
    /**
     * For external users: DO NOT USE. We are in the process of open sourcing
     * extension declaration and executing internal cleanups before it can be
     * used externally.
     *
     * Generated from protobuf field <code>repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE];</code>
     */
    private $declaration;
    /**
     * Any features defined in the specific edition.
     *
     * Generated from protobuf field <code>optional .google.protobuf.FeatureSet features = 50;</code>
     */
    protected $features = null;
    /**
     * The verification state of the range.
     * TODO: flip the default to DECLARATION once all empty ranges
     * are marked as UNVERIFIED.
     *
     * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE];</code>
     */
    protected $verification = null;

    /**
     * Constructor.
     *
     * @param array $data {
     *     Optional. Data for populating the Message object.
     *
     *     @type \Google\Protobuf\Internal\UninterpretedOption[] $uninterpreted_option
     *           The parser stores options it doesn't recognize here. See above.
     *     @type \Google\Protobuf\Internal\ExtensionRangeOptions\Declaration[] $declaration
     *           For external users: DO NOT USE. We are in the process of open sourcing
     *           extension declaration and executing internal cleanups before it can be
     *           used externally.
     *     @type \Google\Protobuf\Internal\FeatureSet $features
     *           Any features defined in the specific edition.
     *     @type int $verification
     *           The verification state of the range.
     *           TODO: flip the default to DECLARATION once all empty ranges
     *           are marked as UNVERIFIED.
     * }
     */
    public function __construct($data = null)
    {
        \GPBMetadata\Google\Protobuf\Internal\Descriptor::initOnce();
        parent::__construct($data);
    }

    /**
     * The parser stores options it doesn't recognize here. See above.
     *
     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
     * @return RepeatedField<\Google\Protobuf\Internal\UninterpretedOption>
     */
    public function getUninterpretedOption()
    {
        return $this->uninterpreted_option;
    }

    /**
     * The parser stores options it doesn't recognize here. See above.
     *
     * Generated from protobuf field <code>repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;</code>
     * @param \Google\Protobuf\Internal\UninterpretedOption[] $var
     * @return $this
     */
    public function setUninterpretedOption(array|RepeatedField $var)
    {
        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\UninterpretedOption::class);
        $this->uninterpreted_option = $arr;

        return $this;
    }

    /**
     * For external users: DO NOT USE. We are in the process of open sourcing
     * extension declaration and executing internal cleanups before it can be
     * used externally.
     *
     * Generated from protobuf field <code>repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE];</code>
     * @return RepeatedField<\Google\Protobuf\Internal\ExtensionRangeOptions\Declaration>
     */
    public function getDeclaration()
    {
        return $this->declaration;
    }

    /**
     * For external users: DO NOT USE. We are in the process of open sourcing
     * extension declaration and executing internal cleanups before it can be
     * used externally.
     *
     * Generated from protobuf field <code>repeated .google.protobuf.ExtensionRangeOptions.Declaration declaration = 2 [retention = RETENTION_SOURCE];</code>
     * @param \Google\Protobuf\Internal\ExtensionRangeOptions\Declaration[] $var
     * @return $this
     */
    public function setDeclaration(array|RepeatedField $var)
    {
        $arr = GPBUtil::checkRepeatedField($var, \Google\Protobuf\Internal\GPBType::MESSAGE, \Google\Protobuf\Internal\ExtensionRangeOptions\Declaration::class);
        $this->declaration = $arr;

        return $this;
    }

    /**
     * Any features defined in the specific edition.
     *
     * Generated from protobuf field <code>optional .google.protobuf.FeatureSet features = 50;</code>
     * @return \Google\Protobuf\Internal\FeatureSet|null
     */
    public function getFeatures()
    {
        return $this->features;
    }

    public function hasFeatures()
    {
        return isset($this->features);
    }

    public function clearFeatures()
    {
        unset($this->features);
    }

    /**
     * Any features defined in the specific edition.
     *
     * Generated from protobuf field <code>optional .google.protobuf.FeatureSet features = 50;</code>
     * @param \Google\Protobuf\Internal\FeatureSet $var
     * @return $this
     */
    public function setFeatures(\Google\Protobuf\Internal\FeatureSet|null $var)
    {
        $this->features = $var;

        return $this;
    }

    /**
     * The verification state of the range.
     * TODO: flip the default to DECLARATION once all empty ranges
     * are marked as UNVERIFIED.
     *
     * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE];</code>
     * @return int one of the values in {@see \Google\Protobuf\Internal\ExtensionRangeOptions\VerificationState}
     */
    public function getVerification()
    {
        return isset($this->verification) ? $this->verification : 1;
    }

    public function hasVerification()
    {
        return isset($this->verification);
    }

    public function clearVerification()
    {
        unset($this->verification);
    }

    /**
     * The verification state of the range.
     * TODO: flip the default to DECLARATION once all empty ranges
     * are marked as UNVERIFIED.
     *
     * Generated from protobuf field <code>optional .google.protobuf.ExtensionRangeOptions.VerificationState verification = 3 [default = UNVERIFIED, retention = RETENTION_SOURCE];</code>
     * @param int $var one of the values in {@see \Google\Protobuf\Internal\ExtensionRangeOptions\VerificationState}
     * @return $this
     */
    public function setVerification(int $var)
    {
        GPBUtil::checkEnum($var, \Google\Protobuf\Internal\ExtensionRangeOptions\VerificationState::class);
        $this->verification = $var;

        return $this;
    }

}

