/*eslint-disable block-scoped-var, id-length, no-control-regex, no-magic-numbers, no-prototype-builtins, no-redeclare, no-shadow, no-var, sort-vars*/
"use strict";

var $protobuf = require("../../minimal");

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

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

$root.MyService = (function() {

    /**
     * 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;
})();

$root.MyRequest = (function() {

    /**
     * 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 (var 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);
        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.MyRequest();
        while (reader.pos < end) {
            var 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;
        var 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 = {};
        var 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;
})();

$root.MyResponse = (function() {

    /**
     * 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 (var 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);
        var end = length === undefined ? reader.len : reader.pos + length, message = new $root.MyResponse();
        while (reader.pos < end) {
            var 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;
        var 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 = {};
        var 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;
})();

module.exports = $root;
