// Copyright 2021 The Pigweed Authors // // 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 // // https://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. import {Status} from '@pigweed/pw_status'; import {Message} from 'google-protobuf'; import { BidirectionalStreamingCall, Call, Callback, ClientStreamingCall, ServerStreamingCall, UnaryCall, } from './call'; import {Channel, Method, MethodType, Service} from './descriptors'; import {PendingCalls, Rpc} from './rpc_classes'; export function methodStubFactory( rpcs: PendingCalls, channel: Channel, method: Method ): MethodStub { switch (method.type) { case MethodType.BIDIRECTIONAL_STREAMING: return new BidirectionalStreamingMethodStub(rpcs, channel, method); case MethodType.CLIENT_STREAMING: return new ClientStreamingMethodStub(rpcs, channel, method); case MethodType.SERVER_STREAMING: return new ServerStreamingMethodStub(rpcs, channel, method); case MethodType.UNARY: return new UnaryMethodStub(rpcs, channel, method); } } export abstract class MethodStub { readonly method: Method; readonly rpcs: PendingCalls; readonly rpc: Rpc; private channel: Channel; constructor(rpcs: PendingCalls, channel: Channel, method: Method) { this.method = method; this.rpcs = rpcs; this.channel = channel; this.rpc = new Rpc(channel, method.service, method); } get id(): number { return this.method.id; } } export class UnaryMethodStub extends MethodStub { invoke( request: Message, onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): UnaryCall { const call = new UnaryCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(request); return call; } open( request: Message, onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): UnaryCall { const call = new UnaryCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(request, true); return call; } async call(request: Message, timeout?: number): Promise<[Status, Message]> { return await this.invoke(request).complete(timeout); } } export class ServerStreamingMethodStub extends MethodStub { invoke( request?: Message, onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): ServerStreamingCall { const call = new ServerStreamingCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(request); return call; } open( request: Message, onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): UnaryCall { const call = new UnaryCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(request, true); return call; } call(request?: Message, timeout?: number): Promise<[Status, Message[]]> { return this.invoke(request).complete(timeout); } } export class ClientStreamingMethodStub extends MethodStub { invoke( onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): ClientStreamingCall { const call = new ClientStreamingCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(); return call; } open( onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): ClientStreamingCall { const call = new ClientStreamingCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(undefined, true); return call; } async call(requests: Array = [], timeout?: number) { return this.invoke().finishAndWait(requests, timeout); } } export class BidirectionalStreamingMethodStub extends MethodStub { invoke( onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): BidirectionalStreamingCall { const call = new BidirectionalStreamingCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(); return call; } open( onNext: Callback = () => {}, onCompleted: Callback = () => {}, onError: Callback = () => {} ): BidirectionalStreamingCall { const call = new BidirectionalStreamingCall( this.rpcs, this.rpc, onNext, onCompleted, onError ); call.invoke(undefined, true); return call; } async call(requests: Array = [], timeout?: number) { return this.invoke().finishAndWait(requests, timeout); } }