Use FnOnce, not FnMut, in Socket::dispatch() functions.

There was never any reason to use FnMut and this significantly
simplifies the job of the borrow checker.
This commit is contained in:
whitequark 2017-08-28 00:59:33 +00:00
parent 5cb2dcd1aa
commit 917f89e14b
5 changed files with 28 additions and 35 deletions

View File

@ -403,30 +403,23 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
} }
fn emit(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> { fn emit(&mut self, sockets: &mut SocketSet, timestamp: u64) -> Result<bool> {
// Borrow checker is being overly careful around closures, so we have let mut limits = self.device.limits();
// to hack around that.
let src_hardware_addr = self.hardware_addr;
let src_protocol_addrs = self.protocol_addrs.as_ref();
let arp_cache = &mut self.arp_cache;
let device = &mut self.device;
let mut limits = device.limits();
limits.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len(); limits.max_transmission_unit -= EthernetFrame::<&[u8]>::header_len();
let mut nothing_to_transmit = true; let mut nothing_to_transmit = true;
for socket in sockets.iter_mut() { for socket in sockets.iter_mut() {
let result = socket.dispatch(timestamp, &limits, &mut |repr, payload| { let result = socket.dispatch(timestamp, &limits, |repr, payload| {
let repr = repr.lower(src_protocol_addrs)?; let repr = repr.lower(self.protocol_addrs.as_ref())?;
match arp_cache.lookup(&repr.dst_addr()) { match self.arp_cache.lookup(&repr.dst_addr()) {
Some(dst_hardware_addr) => { Some(dst_hardware_addr) => {
let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len() + let tx_len = EthernetFrame::<&[u8]>::buffer_len(repr.buffer_len() +
payload.buffer_len()); payload.buffer_len());
let mut tx_buffer = device.transmit(timestamp, tx_len)?; let mut tx_buffer = self.device.transmit(timestamp, tx_len)?;
debug_assert!(tx_buffer.as_ref().len() == tx_len); debug_assert!(tx_buffer.as_ref().len() == tx_len);
let mut frame = EthernetFrame::new(&mut tx_buffer); let mut frame = EthernetFrame::new(&mut tx_buffer);
frame.set_src_addr(src_hardware_addr); frame.set_src_addr(self.hardware_addr);
frame.set_dst_addr(dst_hardware_addr); frame.set_dst_addr(dst_hardware_addr);
frame.set_ethertype(EthernetProtocol::Ipv4); frame.set_ethertype(EthernetProtocol::Ipv4);
@ -447,18 +440,18 @@ impl<'a, 'b, 'c, DeviceT: Device + 'a> Interface<'a, 'b, 'c, DeviceT> {
let payload = ArpRepr::EthernetIpv4 { let payload = ArpRepr::EthernetIpv4 {
operation: ArpOperation::Request, operation: ArpOperation::Request,
source_hardware_addr: src_hardware_addr, source_hardware_addr: self.hardware_addr,
source_protocol_addr: src_addr, source_protocol_addr: src_addr,
target_hardware_addr: EthernetAddress::default(), target_hardware_addr: EthernetAddress::default(),
target_protocol_addr: dst_addr, target_protocol_addr: dst_addr,
}; };
let tx_len = EthernetFrame::<&[u8]>::buffer_len(payload.buffer_len()); let tx_len = EthernetFrame::<&[u8]>::buffer_len(payload.buffer_len());
let mut tx_buffer = device.transmit(timestamp, tx_len)?; let mut tx_buffer = self.device.transmit(timestamp, tx_len)?;
debug_assert!(tx_buffer.as_ref().len() == tx_len); debug_assert!(tx_buffer.as_ref().len() == tx_len);
let mut frame = EthernetFrame::new(&mut tx_buffer); let mut frame = EthernetFrame::new(&mut tx_buffer);
frame.set_src_addr(src_hardware_addr); frame.set_src_addr(self.hardware_addr);
frame.set_dst_addr(EthernetAddress([0xff; 6])); frame.set_dst_addr(EthernetAddress([0xff; 6]));
frame.set_ethertype(EthernetProtocol::Arp); frame.set_ethertype(EthernetProtocol::Arp);

View File

@ -82,8 +82,8 @@ impl<'a, 'b> Socket<'a, 'b> {
} }
pub(crate) fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits, pub(crate) fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits,
emit: &mut F) -> Result<R> emit: F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> { where F: FnOnce(&IpRepr, &IpPayload) -> Result<R> {
dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, limits, emit)) dispatch_socket!(self, |socket [mut]| socket.dispatch(timestamp, limits, emit))
} }
} }

View File

@ -184,8 +184,8 @@ impl<'a, 'b> RawSocket<'a, 'b> {
} }
pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits, pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
emit: &mut F) -> Result<R> emit: F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> { where F: FnOnce(&IpRepr, &IpPayload) -> Result<R> {
fn prepare(protocol: IpProtocol, buffer: &mut [u8]) -> Result<(IpRepr, RawRepr)> { fn prepare(protocol: IpProtocol, buffer: &mut [u8]) -> Result<(IpRepr, RawRepr)> {
match IpVersion::of_packet(buffer.as_ref())? { match IpVersion::of_packet(buffer.as_ref())? {
IpVersion::Ipv4 => { IpVersion::Ipv4 => {
@ -291,7 +291,7 @@ mod test {
let mut socket = socket(buffer(0), buffer(1)); let mut socket = socket(buffer(0), buffer(1));
assert!(socket.can_send()); assert!(socket.can_send());
assert_eq!(socket.dispatch(0, &limits, &mut |_ip_repr, _ip_payload| { assert_eq!(socket.dispatch(0, &limits, |_ip_repr, _ip_payload| {
unreachable!() unreachable!()
}), Err(Error::Exhausted) as Result<()>); }), Err(Error::Exhausted) as Result<()>);
@ -307,14 +307,14 @@ mod test {
}} }}
} }
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| { assert_eq!(socket.dispatch(0, &limits, |ip_repr, ip_payload| {
assert_eq!(ip_repr, &HEADER_REPR); assert_eq!(ip_repr, &HEADER_REPR);
assert_payload_eq!(ip_repr, ip_payload, PACKET_BYTES); assert_payload_eq!(ip_repr, ip_payload, PACKET_BYTES);
Err(Error::Unaddressable) Err(Error::Unaddressable)
}), Err(Error::Unaddressable) as Result<()>); }), Err(Error::Unaddressable) as Result<()>);
/*assert!(!socket.can_send());*/ /*assert!(!socket.can_send());*/
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| { assert_eq!(socket.dispatch(0, &limits, |ip_repr, ip_payload| {
assert_eq!(ip_repr, &HEADER_REPR); assert_eq!(ip_repr, &HEADER_REPR);
assert_payload_eq!(ip_repr, ip_payload, PACKET_BYTES); assert_payload_eq!(ip_repr, ip_payload, PACKET_BYTES);
Ok(()) Ok(())
@ -332,7 +332,7 @@ mod test {
Ipv4Packet::new(&mut wrong_version).set_version(5); Ipv4Packet::new(&mut wrong_version).set_version(5);
assert_eq!(socket.send_slice(&wrong_version[..]), Ok(())); assert_eq!(socket.send_slice(&wrong_version[..]), Ok(()));
assert_eq!(socket.dispatch(0, &limits, &mut |_ip_repr, _ip_payload| { assert_eq!(socket.dispatch(0, &limits, |_ip_repr, _ip_payload| {
unreachable!() unreachable!()
}), Err(Error::Rejected) as Result<()>); }), Err(Error::Rejected) as Result<()>);
@ -340,7 +340,7 @@ mod test {
Ipv4Packet::new(&mut wrong_protocol).set_protocol(IpProtocol::Tcp); Ipv4Packet::new(&mut wrong_protocol).set_protocol(IpProtocol::Tcp);
assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(())); assert_eq!(socket.send_slice(&wrong_protocol[..]), Ok(()));
assert_eq!(socket.dispatch(0, &limits, &mut |_ip_repr, _ip_payload| { assert_eq!(socket.dispatch(0, &limits, |_ip_repr, _ip_payload| {
unreachable!() unreachable!()
}), Err(Error::Rejected) as Result<()>); }), Err(Error::Rejected) as Result<()>);
} }

View File

@ -1091,8 +1091,8 @@ impl<'a> TcpSocket<'a> {
} }
pub(crate) fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits, pub(crate) fn dispatch<F, R>(&mut self, timestamp: u64, limits: &DeviceLimits,
emit: &mut F) -> Result<R> emit: F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> { where F: FnOnce(&IpRepr, &IpPayload) -> Result<R> {
if !self.remote_endpoint.is_specified() { return Err(Error::Exhausted) } if !self.remote_endpoint.is_specified() { return Err(Error::Exhausted) }
if let Some(retransmit_delta) = self.timer.should_retransmit(timestamp) { if let Some(retransmit_delta) = self.timer.should_retransmit(timestamp) {
@ -1392,7 +1392,7 @@ mod test {
let mut buffer = vec![]; let mut buffer = vec![];
let mut limits = DeviceLimits::default(); let mut limits = DeviceLimits::default();
limits.max_transmission_unit = 1520; limits.max_transmission_unit = 1520;
let result = socket.dispatch(timestamp, &limits, &mut |ip_repr, payload| { let result = socket.dispatch(timestamp, &limits, |ip_repr, payload| {
let ip_repr = ip_repr.lower(&[LOCAL_END.addr.into()]).unwrap(); let ip_repr = ip_repr.lower(&[LOCAL_END.addr.into()]).unwrap();
assert_eq!(ip_repr.protocol(), IpProtocol::Tcp); assert_eq!(ip_repr.protocol(), IpProtocol::Tcp);
@ -2869,7 +2869,7 @@ mod test {
limits.max_burst_size = None; limits.max_burst_size = None;
s.send_slice(b"abcdef").unwrap(); s.send_slice(b"abcdef").unwrap();
s.dispatch(0, &limits, &mut |ip_repr, payload| { s.dispatch(0, &limits, |ip_repr, payload| {
let mut buffer = vec![0; payload.buffer_len()]; let mut buffer = vec![0; payload.buffer_len()];
payload.emit(&ip_repr, &mut buffer[..]); payload.emit(&ip_repr, &mut buffer[..]);
let packet = TcpPacket::new(&buffer[..]); let packet = TcpPacket::new(&buffer[..]);
@ -2879,7 +2879,7 @@ mod test {
limits.max_burst_size = Some(4); limits.max_burst_size = Some(4);
s.send_slice(b"abcdef").unwrap(); s.send_slice(b"abcdef").unwrap();
s.dispatch(0, &limits, &mut |ip_repr, payload| { s.dispatch(0, &limits, |ip_repr, payload| {
let mut buffer = vec![0; payload.buffer_len()]; let mut buffer = vec![0; payload.buffer_len()];
payload.emit(&ip_repr, &mut buffer[..]); payload.emit(&ip_repr, &mut buffer[..]);
let packet = TcpPacket::new(&buffer[..]); let packet = TcpPacket::new(&buffer[..]);

View File

@ -203,8 +203,8 @@ impl<'a, 'b> UdpSocket<'a, 'b> {
} }
pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits, pub(crate) fn dispatch<F, R>(&mut self, _timestamp: u64, _limits: &DeviceLimits,
emit: &mut F) -> Result<R> emit: F) -> Result<R>
where F: FnMut(&IpRepr, &IpPayload) -> Result<R> { where F: FnOnce(&IpRepr, &IpPayload) -> Result<R> {
let packet_buf = self.tx_buffer.dequeue()?; let packet_buf = self.tx_buffer.dequeue()?;
net_trace!("[{}]{}:{}: sending {} octets", net_trace!("[{}]{}:{}: sending {} octets",
self.debug_id, self.endpoint, self.debug_id, self.endpoint,
@ -320,7 +320,7 @@ mod test {
assert_eq!(socket.bind(LOCAL_END), Ok(())); assert_eq!(socket.bind(LOCAL_END), Ok(()));
assert!(socket.can_send()); assert!(socket.can_send());
assert_eq!(socket.dispatch(0, &limits, &mut |_ip_repr, _ip_payload| { assert_eq!(socket.dispatch(0, &limits, |_ip_repr, _ip_payload| {
unreachable!() unreachable!()
}), Err(Error::Exhausted) as Result<()>); }), Err(Error::Exhausted) as Result<()>);
@ -338,14 +338,14 @@ mod test {
}} }}
} }
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| { assert_eq!(socket.dispatch(0, &limits, |ip_repr, ip_payload| {
assert_eq!(ip_repr, &LOCAL_IP_REPR); assert_eq!(ip_repr, &LOCAL_IP_REPR);
assert_payload_eq!(ip_repr, ip_payload, &LOCAL_UDP_REPR); assert_payload_eq!(ip_repr, ip_payload, &LOCAL_UDP_REPR);
Err(Error::Unaddressable) Err(Error::Unaddressable)
}), Err(Error::Unaddressable) as Result<()>); }), Err(Error::Unaddressable) as Result<()>);
/*assert!(!socket.can_send());*/ /*assert!(!socket.can_send());*/
assert_eq!(socket.dispatch(0, &limits, &mut |ip_repr, ip_payload| { assert_eq!(socket.dispatch(0, &limits, |ip_repr, ip_payload| {
assert_eq!(ip_repr, &LOCAL_IP_REPR); assert_eq!(ip_repr, &LOCAL_IP_REPR);
assert_payload_eq!(ip_repr, ip_payload, &LOCAL_UDP_REPR); assert_payload_eq!(ip_repr, ip_payload, &LOCAL_UDP_REPR);
Ok(()) Ok(())