pw_rpc: Update packets.ts

* Makes it easier to pass channel, method, service id tuples.
* Adds encodeCancel packet method with corresponding unit tests.

No-Docs-Update-Reason: No changes to public pw_rpc api.
Bug: b/194329554
Change-Id: Ib836aea6fd9453a008cee6272ab6ee8f69f70c7d
Reviewed-on: https://pigweed-review.googlesource.com/c/pigweed/pigweed/+/60942
Commit-Queue: Auto-Submit <auto-submit@pigweed.google.com.iam.gserviceaccount.com>
Reviewed-by: Paul Mathieu <paulmathieu@google.com>
Reviewed-by: Wyatt Hepler <hepler@google.com>
Pigweed-Auto-Submit: Jared Weinstein <jaredweinstein@google.com>
diff --git a/pw_rpc/ts/packets.ts b/pw_rpc/ts/packets.ts
index 0f2733a..5677b03 100644
--- a/pw_rpc/ts/packets.ts
+++ b/pw_rpc/ts/packets.ts
@@ -15,17 +15,20 @@
 /** Functions for working with pw_rpc packets. */
 
 import {Message} from 'google-protobuf';
+import {MethodDescriptorProto} from 'google-protobuf/google/protobuf/descriptor_pb';
 import * as packetPb from 'packet_proto_tspb/packet_proto_tspb_pb/pw_rpc/internal/packet_pb'
 import {Status} from 'pigweed/pw_status/ts/status';
 
+// Channel, Service, Method
+type idSet = [number, number, number];
+
 export function decode(data: Uint8Array): packetPb.RpcPacket {
   return packetPb.RpcPacket.deserializeBinary(data);
 }
 
-export function decodePayload(packet: any, payloadType: any) {
-  const payload = new payloadType();
-  payload.deserializeBinary(packet);
-  return payload;
+export function decodePayload(payload: Uint8Array, payloadType: any): Message {
+  const message = payloadType.deserializeBinary(payload);
+  return message;
 }
 
 export function forServer(packet: packetPb.RpcPacket): boolean {
@@ -43,30 +46,35 @@
   return errorPacket.serializeBinary();
 }
 
-export function encodeRequest(
-    channelId: number, serviceId: number, methodId: number, request?: Message):
-    Uint8Array {
+export function encodeRequest(ids: idSet, request?: Message): Uint8Array {
   const payload: Uint8Array = (typeof request !== 'undefined') ?
       request.serializeBinary() :
       new Uint8Array();
 
   const packet = new packetPb.RpcPacket();
   packet.setType(packetPb.PacketType.REQUEST);
-  packet.setChannelId(channelId);
-  packet.setServiceId(serviceId);
-  packet.setMethodId(methodId);
+  packet.setChannelId(ids[0]);
+  packet.setServiceId(ids[1]);
+  packet.setMethodId(ids[2]);
   packet.setPayload(payload);
   return packet.serializeBinary();
 }
 
-export function encodeResponse(
-    channelId: number, serviceId: number, methodId: number, response: Message):
-    Uint8Array {
+export function encodeResponse(ids: idSet, response: Message): Uint8Array {
   const packet = new packetPb.RpcPacket();
   packet.setType(packetPb.PacketType.RESPONSE);
-  packet.setChannelId(channelId);
-  packet.setServiceId(serviceId);
-  packet.setMethodId(methodId);
+  packet.setChannelId(ids[0]);
+  packet.setServiceId(ids[1]);
+  packet.setMethodId(ids[2]);
   packet.setPayload(response.serializeBinary());
   return packet.serializeBinary();
 }
+
+export function encodeCancel(ids: idSet): Uint8Array {
+  const packet = new packetPb.RpcPacket();
+  packet.setType(packetPb.PacketType.CANCEL);
+  packet.setChannelId(ids[0]);
+  packet.setServiceId(ids[1]);
+  packet.setMethodId(ids[2]);
+  return packet.serializeBinary();
+}
diff --git a/pw_rpc/ts/packets_test.ts b/pw_rpc/ts/packets_test.ts
index c7af9a3..3fcd639 100644
--- a/pw_rpc/ts/packets_test.ts
+++ b/pw_rpc/ts/packets_test.ts
@@ -39,7 +39,7 @@
 
     const dataPacket = new RpcPacket();
     dataPacket.setStatus(321);
-    const data = packets.encodeRequest(1, 2, 3, dataPacket);
+    const data = packets.encodeRequest([1, 2, 3], dataPacket);
     const packet = RpcPacket.deserializeBinary(data);
 
     expect(packet.toObject()).toEqual(goldenRequest.toObject());
@@ -52,7 +52,7 @@
 
     const dataPacket = new RpcPacket();
     dataPacket.setStatus(321);
-    const data = packets.encodeResponse(1, 2, 3, dataPacket);
+    const data = packets.encodeResponse([1, 2, 3], dataPacket);
     const packet = RpcPacket.deserializeBinary(data);
 
     expect(packet.toObject()).toEqual(goldenResponse.toObject());
@@ -75,6 +75,18 @@
     expect(errorPacket.toObject()).toEqual(golden.toObject());
   });
 
+  it('encodeCancel sets packet fields', () => {
+    const goldenCancel = new RpcPacket();
+    goldenCancel.setType(PacketType.CANCEL);
+    goldenCancel.setChannelId(1);
+    goldenCancel.setServiceId(2);
+    goldenCancel.setMethodId(3);
+
+    const data = packets.encodeCancel([1, 2, 3]);
+    const packet = RpcPacket.deserializeBinary(data);
+    expect(packet.toObject()).toEqual(goldenCancel.toObject());
+  });
+
   it('decode with serialized request returns request', () => {
     const request = new RpcPacket();
     request.setType(PacketType.REQUEST);