-
Notifications
You must be signed in to change notification settings - Fork 20
RFC: Network::receive
only returns the desired type of message
#177
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #177 +/- ##
==========================================
- Coverage 86.83% 86.78% -0.06%
==========================================
Files 41 41
Lines 7864 7869 +5
==========================================
Hits 6829 6829
- Misses 1035 1040 +5 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
@@ -155,6 +155,10 @@ pub enum NetworkReceiveError { | |||
BadSocket(#[from] std::io::Error), | |||
} | |||
|
|||
pub trait FromNetworkMessage<T = Self> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems almost like manually reimplementing TryFrom
I think it would be better to split up |
Or, thinking of repair, it could even be |
Hmm... how about making things even simpler. We define Network as something like below: pub trait Network {
async fn send<T: Serialize>(&self, message: &T, to: SocketAddr) -> Result<(), NetworkSendError> {
// implemented by using send_serialized below
}
// definition provided by the structs actually implementing this trait
async fn send_serialized(&self, bytes: &[u8], to: SocketAddr) -> Result<(), NetworkSendError>;
async fn receive<T: DeserializeOwned>(&self) -> Result<T, NetworkReceiveError> {
// implemented by using receive_raw below.
}
// definition provided by the structs actually implementing this trait
async fn receive_raw(&self, buf: &mut [u8]) -> Result<usize, NetworkReceiveError>;
} Now components and send and receive anything they want as long as it can be [de]serialized. |
I'm not sure this would help. I also don't know what the purpose would be to try to receive different message types, if we receive them not in the expected order all calls to And then you give the callers of |
After consulting ChatGPT, I came up with this middle-ground approach using associated types. This keeps the type parameters out of any uses of trait Network {
type Send;
type Recv;
fn send(&self, msg: &Self::Send) -> anyhow::Result<()>;
fn recv(&self) -> anyhow::Result<Self::Recv>;
}
struct UdpNetwork<S: Encode, R: Decode> { /* ... */ }
impl<S: Encode, R: Decode> Network for UdpNetwork<S, R> {
type Send = S;
type Recv = R;
/* ... */
} Also works with type inference: let socket = UdpNetwork::new();
socket.send(&"hello".to_string()).unwrap();
let socket: String = udp.recv().unwrap(); |
Currently, whenever we are doing
Network::receive()
, we need to handle the different variants that we do not care about. In most cases, we ignore the other variants and we simply callreceive()
again.The idea here is to introduce a way to get the
Network
to keep looping till it receives the variant we care about. The PR is still incomplete. I wanted to get some feedback on whether this idea makes sense or not before I do the work to finish it up.We introduce a new trait
FromNetworkMessage
. This trait is implemented by the various types of network messages. Then instead of callingreceive()
, we call e.g.receive::<RepairMessage>()
and do not have to write additional looping code.The only interesting part of the RFC is in
src/network.rs
. You can ignore the rest of the changes.