ref_.rs 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. use core::ops::{Deref, DerefMut};
  2. #[cfg(feature = "socket-raw")]
  3. use socket::RawSocket;
  4. #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
  5. use socket::IcmpSocket;
  6. #[cfg(feature = "socket-udp")]
  7. use socket::UdpSocket;
  8. #[cfg(feature = "socket-tcp")]
  9. use socket::TcpSocket;
  10. /// A trait for tracking a socket usage session.
  11. ///
  12. /// Allows implementation of custom drop logic that runs only if the socket was changed
  13. /// in specific ways. For example, drop logic for UDP would check if the local endpoint
  14. /// has changed, and if yes, notify the socket set.
  15. #[doc(hidden)]
  16. pub trait Session {
  17. fn finish(&mut self) {}
  18. }
  19. #[cfg(feature = "socket-raw")]
  20. impl<'a, 'b> Session for RawSocket<'a, 'b> {}
  21. #[cfg(all(feature = "socket-icmp", any(feature = "proto-ipv4", feature = "proto-ipv6")))]
  22. impl<'a, 'b> Session for IcmpSocket<'a, 'b> {}
  23. #[cfg(feature = "socket-udp")]
  24. impl<'a, 'b> Session for UdpSocket<'a, 'b> {}
  25. #[cfg(feature = "socket-tcp")]
  26. impl<'a> Session for TcpSocket<'a> {}
  27. /// A smart pointer to a socket.
  28. ///
  29. /// Allows the network stack to efficiently determine if the socket state was changed in any way.
  30. pub struct Ref<'a, T: Session + 'a> {
  31. socket: &'a mut T
  32. }
  33. impl<'a, T: Session + 'a> Ref<'a, T> {
  34. /// Wrap a pointer to a socket to make a smart pointer.
  35. ///
  36. /// Calling this function is only necessary if your code is using [into_inner].
  37. ///
  38. /// [into_inner]: #method.into_inner
  39. pub fn new(socket: &'a mut T) -> Self {
  40. Ref { socket }
  41. }
  42. /// Unwrap a smart pointer to a socket.
  43. ///
  44. /// The finalization code is not run. Prompt operation of the network stack depends
  45. /// on wrapping the returned pointer back and dropping it.
  46. ///
  47. /// Calling this function is only necessary to achieve composability if you *must*
  48. /// map a `&mut SocketRef<'a, XSocket>` to a `&'a mut XSocket` (note the lifetimes);
  49. /// be sure to call [new] afterwards.
  50. ///
  51. /// [new]: #method.new
  52. pub fn into_inner(ref_: Self) -> &'a mut T {
  53. ref_.socket
  54. }
  55. }
  56. impl<'a, T: Session> Deref for Ref<'a, T> {
  57. type Target = T;
  58. fn deref(&self) -> &Self::Target {
  59. self.socket
  60. }
  61. }
  62. impl<'a, T: Session> DerefMut for Ref<'a, T> {
  63. fn deref_mut(&mut self) -> &mut Self::Target {
  64. self.socket
  65. }
  66. }
  67. // FIXME: `Session::finish` currently does not do anything, but if it did, this would be a problem,
  68. // because `SocketRef::into_inner` would have to use unsafe code, and there's currently no unsafe
  69. // code in smoltcp at all (other than the `phy` module). The reason it would need unsafe code is
  70. // that it is currently an error to destructure a value that implements Drop (or move out its
  71. // fields in any other way), so it'd have to be transmuted away. This is a deficiency in Rust:
  72. // it is always safe to ignore the Drop impl during destructuring.
  73. //
  74. // impl<'a, T: Session> Drop for Ref<'a, T> {
  75. // fn drop(&mut self) {
  76. // Session::finish(self.socket);
  77. // }
  78. // }