ref_.rs 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. use core::ops::{Deref, DerefMut};
  2. #[cfg(feature = "socket-raw")]
  3. use socket::RawSocket;
  4. #[cfg(feature = "socket-udp")]
  5. use socket::UdpSocket;
  6. #[cfg(feature = "socket-tcp")]
  7. use socket::TcpSocket;
  8. /// A trait for tracking a socket usage session.
  9. ///
  10. /// Allows implementation of custom drop logic that runs only if the socket was changed
  11. /// in specific ways. For example, drop logic for UDP would check if the local endpoint
  12. /// has changed, and if yes, notify the socket set.
  13. #[doc(hidden)]
  14. pub trait Session {
  15. fn finish(&mut self) {}
  16. }
  17. #[cfg(feature = "socket-raw")]
  18. impl<'a, 'b> Session for RawSocket<'a, 'b> {}
  19. #[cfg(feature = "socket-udp")]
  20. impl<'a, 'b> Session for UdpSocket<'a, 'b> {}
  21. #[cfg(feature = "socket-tcp")]
  22. impl<'a> Session for TcpSocket<'a> {}
  23. /// A smart pointer to a socket.
  24. ///
  25. /// Allows the network stack to efficiently determine if the socket state was changed in any way.
  26. pub struct Ref<'a, T: Session + 'a> {
  27. socket: &'a mut T,
  28. consumed: bool,
  29. }
  30. impl<'a, T: Session> Ref<'a, T> {
  31. pub(crate) fn new(socket: &'a mut T) -> Self {
  32. Ref { socket, consumed: false }
  33. }
  34. }
  35. impl<'a, T: Session + 'a> Ref<'a, T> {
  36. pub(crate) fn map<U, F>(mut ref_: Self, f: F) -> Option<Ref<'a, U>>
  37. where U: Session + 'a, F: FnOnce(&'a mut T) -> Option<&'a mut U> {
  38. if let Some(socket) = f(ref_.socket) {
  39. ref_.consumed = true;
  40. Some(Ref::new(socket))
  41. } else {
  42. None
  43. }
  44. }
  45. }
  46. impl<'a, T: Session> Deref for Ref<'a, T> {
  47. type Target = T;
  48. fn deref(&self) -> &Self::Target {
  49. self.socket
  50. }
  51. }
  52. impl<'a, T: Session> DerefMut for Ref<'a, T> {
  53. fn deref_mut(&mut self) -> &mut Self::Target {
  54. self.socket
  55. }
  56. }
  57. impl<'a, T: Session> Drop for Ref<'a, T> {
  58. fn drop(&mut self) {
  59. if !self.consumed {
  60. Session::finish(self.socket);
  61. }
  62. }
  63. }