/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
import * as $protobuf from "../../minimal";

// Common aliases
const $Reader = $protobuf.Reader, $Writer = $protobuf.Writer, $util = $protobuf.util;

// Exported root namespace
const $root = $protobuf.roots.test_rpc || ($protobuf.roots.test_rpc = {});

export const MyService = $root.MyService = (() => {

    /**
     * Constructs a new MyService service.
     * @exports MyService
     * @classdesc Represents a MyService
     * @extends $protobuf.rpc.Service
     * @constructor
     * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
     * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
     * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
     */
    function MyService(rpcImpl, requestDelimited, responseDelimited) {
        $protobuf.rpc.Service.call(this, rpcImpl, requestDelimited, responseDelimited);
    }

    (MyService.prototype = Object.create($protobuf.rpc.Service.prototype)).constructor = MyService;

    /**
     * Creates new MyService service using the specified rpc implementation.
     * @function create
     * @memberof MyService
     * @static
     * @param {$protobuf.RPCImpl} rpcImpl RPC implementation
     * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
     * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
     * @returns {MyService} RPC service. Useful where requests and/or responses are streamed.
     */
    MyService.create = function create(rpcImpl, requestDelimited, responseDelimited) {
        return new this(rpcImpl, requestDelimited, responseDelimited);
    };

    /**
     * Callback as used by {@link MyService#myMethod}.
     * @memberof MyService
     * @typedef MyMethodCallback
     * @type {function}
     * @param {Error|null} error Error, if any
     * @param {MyResponse} [response] MyResponse
     */

    /**
     * Calls MyMethod.
     * @function myMethod
     * @memberof MyService
     * @instance
     * @param {IMyRequest} request MyRequest message or plain object
     * @param {MyService.MyMethodCallback} callback Node-style callback called with the error, if any, and MyResponse
     * @returns {undefined}
     * @variation 1
     */
    Object.defineProperty(MyService.prototype.myMethod = function myMethod(request, callback) {
        return this.rpcCall(myMethod, $root.MyRequest, $root.MyResponse, request, callback);
    }, "name", { value: "MyMethod" });

    /**
     * Calls MyMethod.
     * @function myMethod
     * @memberof MyService
     * @instance
     * @param {IMyRequest} request MyRequest message or plain object
     * @returns {Promise<MyResponse>} Promise
     * @variation 2
     */

    return MyService;
})();

export const MyRequest = $root.MyRequest = (() => {

    /**
     * Properties of a MyRequest.
     * @exports IMyRequest
     * @interface IMyRequest
     * @property {string|null} [path] MyRequest path
     */

    /**
     * Constructs a new MyRequest.
     * @exports MyRequest
     * @classdesc Represents a MyRequest.
     * @implements IMyRequest
     * @constructor
     * @param {IMyRequest=} [properties] Properties to set
     */
    function MyRequest(properties) {
        if (properties)
            for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                if (properties[keys[i]] != null)
                    this[keys[i]] = properties[keys[i]];
    }

    /**
     * MyRequest path.
     * @member {string} path
     * @memberof MyRequest
     * @instance
     */
    MyRequest.prototype.path = "";

    /**
     * Creates a new MyRequest instance using the specified properties.
     * @function create
     * @memberof MyRequest
     * @static
     * @param {IMyRequest=} [properties] Properties to set
     * @returns {MyRequest} MyRequest instance
     */
    MyRequest.create = function create(properties) {
        return new MyRequest(properties);
    };

    /**
     * Encodes the specified MyRequest message. Does not implicitly {@link MyRequest.verify|verify} messages.
     * @function encode
     * @memberof MyRequest
     * @static
     * @param {IMyRequest} message MyRequest message or plain object to encode
     * @param {$protobuf.Writer} [writer] Writer to encode to
     * @returns {$protobuf.Writer} Writer
     */
    MyRequest.encode = function encode(message, writer) {
        if (!writer)
            writer = $Writer.create();
        if (message.path != null && Object.hasOwnProperty.call(message, "path"))
            writer.uint32(/* id 1, wireType 2 =*/10).string(message.path);
        return writer;
    };

    /**
     * Encodes the specified MyRequest message, length delimited. Does not implicitly {@link MyRequest.verify|verify} messages.
     * @function encodeDelimited
     * @memberof MyRequest
     * @static
     * @param {IMyRequest} message MyRequest message or plain object to encode
     * @param {$protobuf.Writer} [writer] Writer to encode to
     * @returns {$protobuf.Writer} Writer
     */
    MyRequest.encodeDelimited = function encodeDelimited(message, writer) {
        return this.encode(message, writer).ldelim();
    };

    /**
     * Decodes a MyRequest message from the specified reader or buffer.
     * @function decode
     * @memberof MyRequest
     * @static
     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
     * @param {number} [length] Message length if known beforehand
     * @returns {MyRequest} MyRequest
     * @throws {Error} If the payload is not a reader or valid buffer
     * @throws {$protobuf.util.ProtocolError} If required fields are missing
     */
    MyRequest.decode = function decode(reader, length) {
        if (!(reader instanceof $Reader))
            reader = $Reader.create(reader);
        let end = length === undefined ? reader.len : reader.pos + length, message = new $root.MyRequest();
        while (reader.pos < end) {
            let tag = reader.uint32();
            switch (tag >>> 3) {
            case 1:
                message.path = reader.string();
                break;
            default:
                reader.skipType(tag & 7);
                break;
            }
        }
        return message;
    };

    /**
     * Decodes a MyRequest message from the specified reader or buffer, length delimited.
     * @function decodeDelimited
     * @memberof MyRequest
     * @static
     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
     * @returns {MyRequest} MyRequest
     * @throws {Error} If the payload is not a reader or valid buffer
     * @throws {$protobuf.util.ProtocolError} If required fields are missing
     */
    MyRequest.decodeDelimited = function decodeDelimited(reader) {
        if (!(reader instanceof $Reader))
            reader = new $Reader(reader);
        return this.decode(reader, reader.uint32());
    };

    /**
     * Verifies a MyRequest message.
     * @function verify
     * @memberof MyRequest
     * @static
     * @param {Object.<string,*>} message Plain object to verify
     * @returns {string|null} `null` if valid, otherwise the reason why it is not
     */
    MyRequest.verify = function verify(message) {
        if (typeof message !== "object" || message === null)
            return "object expected";
        if (message.path != null && message.hasOwnProperty("path"))
            if (!$util.isString(message.path))
                return "path: string expected";
        return null;
    };

    /**
     * Creates a MyRequest message from a plain object. Also converts values to their respective internal types.
     * @function fromObject
     * @memberof MyRequest
     * @static
     * @param {Object.<string,*>} object Plain object
     * @returns {MyRequest} MyRequest
     */
    MyRequest.fromObject = function fromObject(object) {
        if (object instanceof $root.MyRequest)
            return object;
        let message = new $root.MyRequest();
        if (object.path != null)
            message.path = String(object.path);
        return message;
    };

    /**
     * Creates a plain object from a MyRequest message. Also converts values to other types if specified.
     * @function toObject
     * @memberof MyRequest
     * @static
     * @param {MyRequest} message MyRequest
     * @param {$protobuf.IConversionOptions} [options] Conversion options
     * @returns {Object.<string,*>} Plain object
     */
    MyRequest.toObject = function toObject(message, options) {
        if (!options)
            options = {};
        let object = {};
        if (options.defaults)
            object.path = "";
        if (message.path != null && message.hasOwnProperty("path"))
            object.path = message.path;
        return object;
    };

    /**
     * Converts this MyRequest to JSON.
     * @function toJSON
     * @memberof MyRequest
     * @instance
     * @returns {Object.<string,*>} JSON object
     */
    MyRequest.prototype.toJSON = function toJSON() {
        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
    };

    return MyRequest;
})();

export const MyResponse = $root.MyResponse = (() => {

    /**
     * Properties of a MyResponse.
     * @exports IMyResponse
     * @interface IMyResponse
     * @property {number|null} [status] MyResponse status
     */

    /**
     * Constructs a new MyResponse.
     * @exports MyResponse
     * @classdesc Represents a MyResponse.
     * @implements IMyResponse
     * @constructor
     * @param {IMyResponse=} [properties] Properties to set
     */
    function MyResponse(properties) {
        if (properties)
            for (let keys = Object.keys(properties), i = 0; i < keys.length; ++i)
                if (properties[keys[i]] != null)
                    this[keys[i]] = properties[keys[i]];
    }

    /**
     * MyResponse status.
     * @member {number} status
     * @memberof MyResponse
     * @instance
     */
    MyResponse.prototype.status = 0;

    /**
     * Creates a new MyResponse instance using the specified properties.
     * @function create
     * @memberof MyResponse
     * @static
     * @param {IMyResponse=} [properties] Properties to set
     * @returns {MyResponse} MyResponse instance
     */
    MyResponse.create = function create(properties) {
        return new MyResponse(properties);
    };

    /**
     * Encodes the specified MyResponse message. Does not implicitly {@link MyResponse.verify|verify} messages.
     * @function encode
     * @memberof MyResponse
     * @static
     * @param {IMyResponse} message MyResponse message or plain object to encode
     * @param {$protobuf.Writer} [writer] Writer to encode to
     * @returns {$protobuf.Writer} Writer
     */
    MyResponse.encode = function encode(message, writer) {
        if (!writer)
            writer = $Writer.create();
        if (message.status != null && Object.hasOwnProperty.call(message, "status"))
            writer.uint32(/* id 2, wireType 0 =*/16).int32(message.status);
        return writer;
    };

    /**
     * Encodes the specified MyResponse message, length delimited. Does not implicitly {@link MyResponse.verify|verify} messages.
     * @function encodeDelimited
     * @memberof MyResponse
     * @static
     * @param {IMyResponse} message MyResponse message or plain object to encode
     * @param {$protobuf.Writer} [writer] Writer to encode to
     * @returns {$protobuf.Writer} Writer
     */
    MyResponse.encodeDelimited = function encodeDelimited(message, writer) {
        return this.encode(message, writer).ldelim();
    };

    /**
     * Decodes a MyResponse message from the specified reader or buffer.
     * @function decode
     * @memberof MyResponse
     * @static
     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
     * @param {number} [length] Message length if known beforehand
     * @returns {MyResponse} MyResponse
     * @throws {Error} If the payload is not a reader or valid buffer
     * @throws {$protobuf.util.ProtocolError} If required fields are missing
     */
    MyResponse.decode = function decode(reader, length) {
        if (!(reader instanceof $Reader))
            reader = $Reader.create(reader);
        let end = length === undefined ? reader.len : reader.pos + length, message = new $root.MyResponse();
        while (reader.pos < end) {
            let tag = reader.uint32();
            switch (tag >>> 3) {
            case 2:
                message.status = reader.int32();
                break;
            default:
                reader.skipType(tag & 7);
                break;
            }
        }
        return message;
    };

    /**
     * Decodes a MyResponse message from the specified reader or buffer, length delimited.
     * @function decodeDelimited
     * @memberof MyResponse
     * @static
     * @param {$protobuf.Reader|Uint8Array} reader Reader or buffer to decode from
     * @returns {MyResponse} MyResponse
     * @throws {Error} If the payload is not a reader or valid buffer
     * @throws {$protobuf.util.ProtocolError} If required fields are missing
     */
    MyResponse.decodeDelimited = function decodeDelimited(reader) {
        if (!(reader instanceof $Reader))
            reader = new $Reader(reader);
        return this.decode(reader, reader.uint32());
    };

    /**
     * Verifies a MyResponse message.
     * @function verify
     * @memberof MyResponse
     * @static
     * @param {Object.<string,*>} message Plain object to verify
     * @returns {string|null} `null` if valid, otherwise the reason why it is not
     */
    MyResponse.verify = function verify(message) {
        if (typeof message !== "object" || message === null)
            return "object expected";
        if (message.status != null && message.hasOwnProperty("status"))
            if (!$util.isInteger(message.status))
                return "status: integer expected";
        return null;
    };

    /**
     * Creates a MyResponse message from a plain object. Also converts values to their respective internal types.
     * @function fromObject
     * @memberof MyResponse
     * @static
     * @param {Object.<string,*>} object Plain object
     * @returns {MyResponse} MyResponse
     */
    MyResponse.fromObject = function fromObject(object) {
        if (object instanceof $root.MyResponse)
            return object;
        let message = new $root.MyResponse();
        if (object.status != null)
            message.status = object.status | 0;
        return message;
    };

    /**
     * Creates a plain object from a MyResponse message. Also converts values to other types if specified.
     * @function toObject
     * @memberof MyResponse
     * @static
     * @param {MyResponse} message MyResponse
     * @param {$protobuf.IConversionOptions} [options] Conversion options
     * @returns {Object.<string,*>} Plain object
     */
    MyResponse.toObject = function toObject(message, options) {
        if (!options)
            options = {};
        let object = {};
        if (options.defaults)
            object.status = 0;
        if (message.status != null && message.hasOwnProperty("status"))
            object.status = message.status;
        return object;
    };

    /**
     * Converts this MyResponse to JSON.
     * @function toJSON
     * @memberof MyResponse
     * @instance
     * @returns {Object.<string,*>} JSON object
     */
    MyResponse.prototype.toJSON = function toJSON() {
        return this.constructor.toObject(this, $protobuf.util.toJSONOptions);
    };

    return MyResponse;
})();

export { $root as default };
