starpc 0.45.0 → 0.46.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/echo/echo.pb.js +1 -1
- package/dist/mock/mock.pb.js +1 -1
- package/dist/rpcstream/rpcstream.pb.js +1 -1
- package/dist/srpc/rpcproto.pb.js +1 -1
- package/echo/Cargo.toml +0 -4
- package/echo/echo.pb.go +1 -1
- package/echo/echo.pb.rs +9 -0
- package/echo/echo.pb.ts +1 -1
- package/echo/echo_e2e_test.cpp +1 -1
- package/echo/echo_srpc.pb.cpp +29 -41
- package/echo/echo_srpc.pb.go +1 -1
- package/echo/echo_srpc.pb.hpp +109 -132
- package/echo/echo_srpc.pb.rs +312 -0
- package/echo/gen/mod.rs +15 -2
- package/echo/main.rs +9 -0
- package/go.mod +3 -2
- package/go.sum +6 -4
- package/mock/mock.pb.go +1 -1
- package/mock/mock.pb.rs +9 -0
- package/mock/mock.pb.ts +1 -1
- package/mock/mock_srpc.pb.cpp +11 -14
- package/mock/mock_srpc.pb.go +1 -1
- package/mock/mock_srpc.pb.hpp +31 -35
- package/mock/mock_srpc.pb.rs +103 -0
- package/package.json +1 -1
- package/srpc/Cargo.toml +1 -2
- package/srpc/client-rpc.cpp +1 -1
- package/srpc/client.cpp +1 -1
- package/srpc/common-rpc.cpp +1 -1
- package/srpc/lib.rs +1 -0
- package/srpc/mux.cpp +1 -1
- package/srpc/packet.cpp +1 -1
- package/srpc/proto.rs +5 -0
- package/srpc/rpcproto.pb.go +1 -1
- package/srpc/rpcproto.pb.rs +62 -0
- package/srpc/rpcproto.pb.ts +1 -1
- package/srpc/rpcstream/mod.rs +38 -0
- package/srpc/rpcstream/proto.rs +286 -0
- package/srpc/rpcstream/stream.rs +517 -0
- package/srpc/rpcstream/writer.rs +150 -0
- package/srpc/server-rpc.cpp +1 -1
- package/echo/build.rs +0 -15
- package/srpc/build.rs +0 -15
- package/srpc/proto/mod.rs +0 -10
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
// Code generated by protoc-gen-starpc-rust. DO NOT EDIT.
|
|
2
|
+
// protoc-gen-starpc-rust version: v0.45.1-0.20260203090429-3e915608d4e8
|
|
3
|
+
// source: github.com/aperturerobotics/starpc/mock/mock.proto
|
|
4
|
+
|
|
5
|
+
#[allow(unused_imports)]
|
|
6
|
+
use starpc::StreamExt;
|
|
7
|
+
|
|
8
|
+
/// Service ID for Mock.
|
|
9
|
+
pub const MOCK_SERVICE_ID: &str = "e2e.mock.Mock";
|
|
10
|
+
|
|
11
|
+
/// Client trait for Mock.
|
|
12
|
+
#[starpc::async_trait]
|
|
13
|
+
pub trait MockClient: Send + Sync {
|
|
14
|
+
/// MockRequest.
|
|
15
|
+
async fn mock_request(&self, request: &MockMsg) -> starpc::Result<MockMsg>;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/// Client implementation for Mock.
|
|
19
|
+
pub struct MockClientImpl<C> {
|
|
20
|
+
client: C,
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
impl<C: starpc::Client> MockClientImpl<C> {
|
|
24
|
+
/// Creates a new client.
|
|
25
|
+
pub fn new(client: C) -> Self {
|
|
26
|
+
Self { client }
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
#[starpc::async_trait]
|
|
31
|
+
impl<C: starpc::Client + 'static> MockClient for MockClientImpl<C> {
|
|
32
|
+
async fn mock_request(&self, request: &MockMsg) -> starpc::Result<MockMsg> {
|
|
33
|
+
self.client.exec_call("e2e.mock.Mock", "MockRequest", request).await
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/// Server trait for Mock.
|
|
38
|
+
#[starpc::async_trait]
|
|
39
|
+
pub trait MockServer: Send + Sync {
|
|
40
|
+
/// MockRequest.
|
|
41
|
+
async fn mock_request(&self, request: MockMsg) -> starpc::Result<MockMsg>;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const MOCK_METHOD_IDS: &[&str] = &[
|
|
45
|
+
"MockRequest",
|
|
46
|
+
];
|
|
47
|
+
|
|
48
|
+
/// Handler for Mock.
|
|
49
|
+
pub struct MockHandler<S: MockServer> {
|
|
50
|
+
server: std::sync::Arc<S>,
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
impl<S: MockServer + 'static> MockHandler<S> {
|
|
54
|
+
/// Creates a new handler wrapping the server implementation.
|
|
55
|
+
pub fn new(server: S) -> Self {
|
|
56
|
+
Self { server: std::sync::Arc::new(server) }
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/// Creates a new handler with a shared server.
|
|
60
|
+
pub fn with_arc(server: std::sync::Arc<S>) -> Self {
|
|
61
|
+
Self { server }
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
#[starpc::async_trait]
|
|
66
|
+
impl<S: MockServer + 'static> starpc::Invoker for MockHandler<S> {
|
|
67
|
+
async fn invoke_method(
|
|
68
|
+
&self,
|
|
69
|
+
_service_id: &str,
|
|
70
|
+
method_id: &str,
|
|
71
|
+
stream: Box<dyn starpc::Stream>,
|
|
72
|
+
) -> (bool, starpc::Result<()>) {
|
|
73
|
+
match method_id {
|
|
74
|
+
"MockRequest" => {
|
|
75
|
+
let request: MockMsg = match stream.msg_recv().await {
|
|
76
|
+
Ok(r) => r,
|
|
77
|
+
Err(e) => return (true, Err(e)),
|
|
78
|
+
};
|
|
79
|
+
match self.server.mock_request(request).await {
|
|
80
|
+
Ok(response) => {
|
|
81
|
+
if let Err(e) = stream.msg_send(&response).await {
|
|
82
|
+
return (true, Err(e));
|
|
83
|
+
}
|
|
84
|
+
(true, Ok(()))
|
|
85
|
+
}
|
|
86
|
+
Err(e) => (true, Err(e)),
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
_ => (false, Err(starpc::Error::Unimplemented)),
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
impl<S: MockServer + 'static> starpc::Handler for MockHandler<S> {
|
|
95
|
+
fn service_id(&self) -> &'static str {
|
|
96
|
+
"e2e.mock.Mock"
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
fn method_ids(&self) -> &'static [&'static str] {
|
|
100
|
+
MOCK_METHOD_IDS
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
package/package.json
CHANGED
package/srpc/Cargo.toml
CHANGED
package/srpc/client-rpc.cpp
CHANGED
package/srpc/client.cpp
CHANGED
package/srpc/common-rpc.cpp
CHANGED
package/srpc/lib.rs
CHANGED
package/srpc/mux.cpp
CHANGED
package/srpc/packet.cpp
CHANGED
package/srpc/proto.rs
ADDED
package/srpc/rpcproto.pb.go
CHANGED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// @generated
|
|
2
|
+
// This file is @generated by prost-build.
|
|
3
|
+
/// Packet is a message sent over a srpc packet connection.
|
|
4
|
+
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
|
5
|
+
pub struct Packet {
|
|
6
|
+
/// Body is the packet body.
|
|
7
|
+
#[prost(oneof="packet::Body", tags="1, 2, 3")]
|
|
8
|
+
pub body: ::core::option::Option<packet::Body>,
|
|
9
|
+
}
|
|
10
|
+
/// Nested message and enum types in `Packet`.
|
|
11
|
+
pub mod packet {
|
|
12
|
+
/// Body is the packet body.
|
|
13
|
+
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Oneof)]
|
|
14
|
+
pub enum Body {
|
|
15
|
+
/// CallStart initiates a new call.
|
|
16
|
+
#[prost(message, tag="1")]
|
|
17
|
+
CallStart(super::CallStart),
|
|
18
|
+
/// CallData is a message in a streaming RPC sequence.
|
|
19
|
+
#[prost(message, tag="2")]
|
|
20
|
+
CallData(super::CallData),
|
|
21
|
+
/// CallCancel cancels the call.
|
|
22
|
+
#[prost(bool, tag="3")]
|
|
23
|
+
CallCancel(bool),
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
/// CallStart requests starting a new RPC call.
|
|
27
|
+
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
|
28
|
+
pub struct CallStart {
|
|
29
|
+
/// RpcService is the service to contact.
|
|
30
|
+
/// Must be set.
|
|
31
|
+
#[prost(string, tag="1")]
|
|
32
|
+
pub rpc_service: ::prost::alloc::string::String,
|
|
33
|
+
/// RpcMethod is the RPC method to call.
|
|
34
|
+
/// Must be set.
|
|
35
|
+
#[prost(string, tag="2")]
|
|
36
|
+
pub rpc_method: ::prost::alloc::string::String,
|
|
37
|
+
/// Data contains the request or the first message in the stream.
|
|
38
|
+
/// Optional if streaming.
|
|
39
|
+
#[prost(bytes="vec", tag="3")]
|
|
40
|
+
pub data: ::prost::alloc::vec::Vec<u8>,
|
|
41
|
+
/// DataIsZero indicates Data is set with an empty message.
|
|
42
|
+
#[prost(bool, tag="4")]
|
|
43
|
+
pub data_is_zero: bool,
|
|
44
|
+
}
|
|
45
|
+
/// CallData contains a message in a streaming RPC sequence.
|
|
46
|
+
#[derive(Clone, PartialEq, Eq, Hash, ::prost::Message)]
|
|
47
|
+
pub struct CallData {
|
|
48
|
+
/// Data contains the packet in the sequence.
|
|
49
|
+
#[prost(bytes="vec", tag="1")]
|
|
50
|
+
pub data: ::prost::alloc::vec::Vec<u8>,
|
|
51
|
+
/// DataIsZero indicates Data is set with an empty message.
|
|
52
|
+
#[prost(bool, tag="2")]
|
|
53
|
+
pub data_is_zero: bool,
|
|
54
|
+
/// Complete indicates the RPC call is completed.
|
|
55
|
+
#[prost(bool, tag="3")]
|
|
56
|
+
pub complete: bool,
|
|
57
|
+
/// Error contains any error that caused the RPC to fail.
|
|
58
|
+
/// If set, implies complete=true.
|
|
59
|
+
#[prost(string, tag="4")]
|
|
60
|
+
pub error: ::prost::alloc::string::String,
|
|
61
|
+
}
|
|
62
|
+
// @@protoc_insertion_point(module)
|
package/srpc/rpcproto.pb.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// @generated by protoc-gen-es-lite unknown with parameter "ts_nocheck=false
|
|
1
|
+
// @generated by protoc-gen-es-lite unknown with parameter "target=ts,ts_nocheck=false"
|
|
2
2
|
// @generated from file github.com/aperturerobotics/starpc/srpc/rpcproto.proto (package srpc, syntax proto3)
|
|
3
3
|
/* eslint-disable */
|
|
4
4
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
//! RpcStream module for nested RPC calls.
|
|
2
|
+
//!
|
|
3
|
+
//! This module enables nesting RPC calls within RPC calls, supporting
|
|
4
|
+
//! component-based architectures where different components expose different
|
|
5
|
+
//! services via sub-streams.
|
|
6
|
+
//!
|
|
7
|
+
//! # Overview
|
|
8
|
+
//!
|
|
9
|
+
//! The rpcstream protocol works as follows:
|
|
10
|
+
//! 1. Client opens a bidirectional stream to the server
|
|
11
|
+
//! 2. Client sends `RpcStreamInit` with the target component ID
|
|
12
|
+
//! 3. Server looks up the component and sends `RpcAck`
|
|
13
|
+
//! 4. Both sides exchange `RpcStreamPacket::Data` containing nested RPC packets
|
|
14
|
+
//!
|
|
15
|
+
//! # Example
|
|
16
|
+
//!
|
|
17
|
+
//! ```rust,ignore
|
|
18
|
+
//! use starpc::rpcstream::{open_rpc_stream, RpcStreamGetter};
|
|
19
|
+
//!
|
|
20
|
+
//! // Client side: open a stream to a component
|
|
21
|
+
//! let stream = my_service.rpc_stream().await?;
|
|
22
|
+
//! let rpc_stream = open_rpc_stream(stream, "my-component", true).await?;
|
|
23
|
+
//!
|
|
24
|
+
//! // Server side: handle incoming rpc stream
|
|
25
|
+
//! let getter: RpcStreamGetter = Arc::new(|ctx, component_id, released| {
|
|
26
|
+
//! // Look up the invoker for this component
|
|
27
|
+
//! Some((invoker, release_fn))
|
|
28
|
+
//! });
|
|
29
|
+
//! handle_rpc_stream(stream, getter).await?;
|
|
30
|
+
//! ```
|
|
31
|
+
|
|
32
|
+
mod proto;
|
|
33
|
+
mod stream;
|
|
34
|
+
mod writer;
|
|
35
|
+
|
|
36
|
+
pub use proto::*;
|
|
37
|
+
pub use stream::*;
|
|
38
|
+
pub use writer::*;
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
//! Protocol buffer types for rpcstream.
|
|
2
|
+
//!
|
|
3
|
+
//! These types are defined manually to match the rpcstream.proto definitions.
|
|
4
|
+
//! They will be generated via protoc-gen-prost in a future update.
|
|
5
|
+
|
|
6
|
+
use bytes::{Buf, BufMut, Bytes};
|
|
7
|
+
use prost::{DecodeError, Message};
|
|
8
|
+
|
|
9
|
+
/// RpcStreamPacket is a packet encapsulating data for a RPC stream.
|
|
10
|
+
#[derive(Clone, PartialEq, Debug, Default)]
|
|
11
|
+
pub struct RpcStreamPacket {
|
|
12
|
+
/// Body of the packet.
|
|
13
|
+
pub body: Option<RpcStreamPacketBody>,
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/// Body variants for RpcStreamPacket.
|
|
17
|
+
#[derive(Clone, PartialEq, Debug)]
|
|
18
|
+
pub enum RpcStreamPacketBody {
|
|
19
|
+
/// Init is the first packet in the stream, sent by the initiator.
|
|
20
|
+
Init(RpcStreamInit),
|
|
21
|
+
/// Ack is sent in response to Init, by the server.
|
|
22
|
+
Ack(RpcAck),
|
|
23
|
+
/// Data is the encapsulated data packet.
|
|
24
|
+
Data(Bytes),
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/// RpcStreamInit is the first message in a RPC stream.
|
|
28
|
+
#[derive(Clone, PartialEq, Debug, Default)]
|
|
29
|
+
pub struct RpcStreamInit {
|
|
30
|
+
/// ComponentId is the identifier of the component making the request.
|
|
31
|
+
pub component_id: String,
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/// RpcAck is the acknowledgment message in a RPC stream.
|
|
35
|
+
#[derive(Clone, PartialEq, Debug, Default)]
|
|
36
|
+
pub struct RpcAck {
|
|
37
|
+
/// Error indicates there was some error setting up the stream.
|
|
38
|
+
pub error: String,
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Manual Message implementation for RpcStreamInit
|
|
42
|
+
impl Message for RpcStreamInit {
|
|
43
|
+
fn encode_raw(&self, buf: &mut impl BufMut)
|
|
44
|
+
where
|
|
45
|
+
Self: Sized,
|
|
46
|
+
{
|
|
47
|
+
if !self.component_id.is_empty() {
|
|
48
|
+
prost::encoding::string::encode(1, &self.component_id, buf);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
fn merge_field(
|
|
53
|
+
&mut self,
|
|
54
|
+
tag: u32,
|
|
55
|
+
wire_type: prost::encoding::WireType,
|
|
56
|
+
buf: &mut impl Buf,
|
|
57
|
+
ctx: prost::encoding::DecodeContext,
|
|
58
|
+
) -> Result<(), DecodeError>
|
|
59
|
+
where
|
|
60
|
+
Self: Sized,
|
|
61
|
+
{
|
|
62
|
+
match tag {
|
|
63
|
+
1 => prost::encoding::string::merge(wire_type, &mut self.component_id, buf, ctx),
|
|
64
|
+
_ => prost::encoding::skip_field(wire_type, tag, buf, ctx),
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn encoded_len(&self) -> usize {
|
|
69
|
+
let mut len = 0;
|
|
70
|
+
if !self.component_id.is_empty() {
|
|
71
|
+
len += prost::encoding::string::encoded_len(1, &self.component_id);
|
|
72
|
+
}
|
|
73
|
+
len
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
fn clear(&mut self) {
|
|
77
|
+
self.component_id.clear();
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Manual Message implementation for RpcAck
|
|
82
|
+
impl Message for RpcAck {
|
|
83
|
+
fn encode_raw(&self, buf: &mut impl BufMut)
|
|
84
|
+
where
|
|
85
|
+
Self: Sized,
|
|
86
|
+
{
|
|
87
|
+
if !self.error.is_empty() {
|
|
88
|
+
prost::encoding::string::encode(1, &self.error, buf);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
fn merge_field(
|
|
93
|
+
&mut self,
|
|
94
|
+
tag: u32,
|
|
95
|
+
wire_type: prost::encoding::WireType,
|
|
96
|
+
buf: &mut impl Buf,
|
|
97
|
+
ctx: prost::encoding::DecodeContext,
|
|
98
|
+
) -> Result<(), DecodeError>
|
|
99
|
+
where
|
|
100
|
+
Self: Sized,
|
|
101
|
+
{
|
|
102
|
+
match tag {
|
|
103
|
+
1 => prost::encoding::string::merge(wire_type, &mut self.error, buf, ctx),
|
|
104
|
+
_ => prost::encoding::skip_field(wire_type, tag, buf, ctx),
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
fn encoded_len(&self) -> usize {
|
|
109
|
+
let mut len = 0;
|
|
110
|
+
if !self.error.is_empty() {
|
|
111
|
+
len += prost::encoding::string::encoded_len(1, &self.error);
|
|
112
|
+
}
|
|
113
|
+
len
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
fn clear(&mut self) {
|
|
117
|
+
self.error.clear();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// Manual Message implementation for RpcStreamPacket
|
|
122
|
+
impl Message for RpcStreamPacket {
|
|
123
|
+
fn encode_raw(&self, buf: &mut impl BufMut)
|
|
124
|
+
where
|
|
125
|
+
Self: Sized,
|
|
126
|
+
{
|
|
127
|
+
match &self.body {
|
|
128
|
+
Some(RpcStreamPacketBody::Init(init)) => {
|
|
129
|
+
// Tag 1, wire type 2 (length-delimited)
|
|
130
|
+
prost::encoding::message::encode(1, init, buf);
|
|
131
|
+
}
|
|
132
|
+
Some(RpcStreamPacketBody::Ack(ack)) => {
|
|
133
|
+
// Tag 2, wire type 2 (length-delimited)
|
|
134
|
+
prost::encoding::message::encode(2, ack, buf);
|
|
135
|
+
}
|
|
136
|
+
Some(RpcStreamPacketBody::Data(data)) => {
|
|
137
|
+
// Tag 3, wire type 2 (length-delimited)
|
|
138
|
+
prost::encoding::bytes::encode(3, data, buf);
|
|
139
|
+
}
|
|
140
|
+
None => {}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
fn merge_field(
|
|
145
|
+
&mut self,
|
|
146
|
+
tag: u32,
|
|
147
|
+
wire_type: prost::encoding::WireType,
|
|
148
|
+
buf: &mut impl Buf,
|
|
149
|
+
ctx: prost::encoding::DecodeContext,
|
|
150
|
+
) -> Result<(), DecodeError>
|
|
151
|
+
where
|
|
152
|
+
Self: Sized,
|
|
153
|
+
{
|
|
154
|
+
match tag {
|
|
155
|
+
1 => {
|
|
156
|
+
let mut init = RpcStreamInit::default();
|
|
157
|
+
prost::encoding::message::merge(wire_type, &mut init, buf, ctx)?;
|
|
158
|
+
self.body = Some(RpcStreamPacketBody::Init(init));
|
|
159
|
+
Ok(())
|
|
160
|
+
}
|
|
161
|
+
2 => {
|
|
162
|
+
let mut ack = RpcAck::default();
|
|
163
|
+
prost::encoding::message::merge(wire_type, &mut ack, buf, ctx)?;
|
|
164
|
+
self.body = Some(RpcStreamPacketBody::Ack(ack));
|
|
165
|
+
Ok(())
|
|
166
|
+
}
|
|
167
|
+
3 => {
|
|
168
|
+
let mut data = Bytes::default();
|
|
169
|
+
prost::encoding::bytes::merge(wire_type, &mut data, buf, ctx)?;
|
|
170
|
+
self.body = Some(RpcStreamPacketBody::Data(data));
|
|
171
|
+
Ok(())
|
|
172
|
+
}
|
|
173
|
+
_ => prost::encoding::skip_field(wire_type, tag, buf, ctx),
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
fn encoded_len(&self) -> usize {
|
|
178
|
+
match &self.body {
|
|
179
|
+
Some(RpcStreamPacketBody::Init(init)) => prost::encoding::message::encoded_len(1, init),
|
|
180
|
+
Some(RpcStreamPacketBody::Ack(ack)) => prost::encoding::message::encoded_len(2, ack),
|
|
181
|
+
Some(RpcStreamPacketBody::Data(data)) => prost::encoding::bytes::encoded_len(3, data),
|
|
182
|
+
None => 0,
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
fn clear(&mut self) {
|
|
187
|
+
self.body = None;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
impl RpcStreamPacket {
|
|
192
|
+
/// Creates a new Init packet.
|
|
193
|
+
pub fn new_init(component_id: String) -> Self {
|
|
194
|
+
Self {
|
|
195
|
+
body: Some(RpcStreamPacketBody::Init(RpcStreamInit { component_id })),
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/// Creates a new Ack packet.
|
|
200
|
+
pub fn new_ack(error: String) -> Self {
|
|
201
|
+
Self {
|
|
202
|
+
body: Some(RpcStreamPacketBody::Ack(RpcAck { error })),
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/// Creates a new Data packet.
|
|
207
|
+
pub fn new_data(data: Bytes) -> Self {
|
|
208
|
+
Self {
|
|
209
|
+
body: Some(RpcStreamPacketBody::Data(data)),
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
#[cfg(test)]
|
|
215
|
+
mod tests {
|
|
216
|
+
use super::*;
|
|
217
|
+
|
|
218
|
+
#[test]
|
|
219
|
+
fn test_rpc_stream_init_encode_decode() {
|
|
220
|
+
let init = RpcStreamInit {
|
|
221
|
+
component_id: "test-component".to_string(),
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
let encoded = init.encode_to_vec();
|
|
225
|
+
let decoded = RpcStreamInit::decode(&encoded[..]).unwrap();
|
|
226
|
+
|
|
227
|
+
assert_eq!(init, decoded);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
#[test]
|
|
231
|
+
fn test_rpc_ack_encode_decode() {
|
|
232
|
+
let ack = RpcAck {
|
|
233
|
+
error: "test error".to_string(),
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
let encoded = ack.encode_to_vec();
|
|
237
|
+
let decoded = RpcAck::decode(&encoded[..]).unwrap();
|
|
238
|
+
|
|
239
|
+
assert_eq!(ack, decoded);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
#[test]
|
|
243
|
+
fn test_rpc_stream_packet_init() {
|
|
244
|
+
let packet = RpcStreamPacket::new_init("my-component".to_string());
|
|
245
|
+
|
|
246
|
+
let encoded = packet.encode_to_vec();
|
|
247
|
+
let decoded = RpcStreamPacket::decode(&encoded[..]).unwrap();
|
|
248
|
+
|
|
249
|
+
match decoded.body {
|
|
250
|
+
Some(RpcStreamPacketBody::Init(init)) => {
|
|
251
|
+
assert_eq!(init.component_id, "my-component");
|
|
252
|
+
}
|
|
253
|
+
_ => panic!("Expected Init body"),
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
#[test]
|
|
258
|
+
fn test_rpc_stream_packet_ack() {
|
|
259
|
+
let packet = RpcStreamPacket::new_ack("".to_string());
|
|
260
|
+
|
|
261
|
+
let encoded = packet.encode_to_vec();
|
|
262
|
+
let decoded = RpcStreamPacket::decode(&encoded[..]).unwrap();
|
|
263
|
+
|
|
264
|
+
match decoded.body {
|
|
265
|
+
Some(RpcStreamPacketBody::Ack(ack)) => {
|
|
266
|
+
assert!(ack.error.is_empty());
|
|
267
|
+
}
|
|
268
|
+
_ => panic!("Expected Ack body"),
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
#[test]
|
|
273
|
+
fn test_rpc_stream_packet_data() {
|
|
274
|
+
let packet = RpcStreamPacket::new_data(Bytes::from(vec![1, 2, 3, 4]));
|
|
275
|
+
|
|
276
|
+
let encoded = packet.encode_to_vec();
|
|
277
|
+
let decoded = RpcStreamPacket::decode(&encoded[..]).unwrap();
|
|
278
|
+
|
|
279
|
+
match decoded.body {
|
|
280
|
+
Some(RpcStreamPacketBody::Data(data)) => {
|
|
281
|
+
assert_eq!(&data[..], &[1, 2, 3, 4]);
|
|
282
|
+
}
|
|
283
|
+
_ => panic!("Expected Data body"),
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|