ref_.rs 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. use core::ops::{Deref, DerefMut};
  2. /// A trait for tracking a socket usage session.
  3. ///
  4. /// Allows implementation of custom drop logic that runs only if the socket was changed
  5. /// in specific ways. For example, drop logic for UDP would check if the local endpoint
  6. /// has changed, and if yes, notify the socket set.
  7. #[doc(hidden)]
  8. pub trait Session {
  9. fn finish(&mut self) {}
  10. }
  11. #[cfg(feature = "socket-raw")]
  12. impl<'a> Session for crate::socket::RawSocket<'a> {}
  13. #[cfg(all(
  14. feature = "socket-icmp",
  15. any(feature = "proto-ipv4", feature = "proto-ipv6")
  16. ))]
  17. impl<'a> Session for crate::socket::IcmpSocket<'a> {}
  18. #[cfg(feature = "socket-udp")]
  19. impl<'a> Session for crate::socket::UdpSocket<'a> {}
  20. #[cfg(feature = "socket-tcp")]
  21. impl<'a> Session for crate::socket::TcpSocket<'a> {}
  22. #[cfg(feature = "socket-dhcpv4")]
  23. impl Session for crate::socket::Dhcpv4Socket {}
  24. /// A smart pointer to a socket.
  25. ///
  26. /// Allows the network stack to efficiently determine if the socket state was changed in any way.
  27. pub struct Ref<'a, T: Session + 'a> {
  28. /// Reference to the socket.
  29. ///
  30. /// This is almost always `Some` except when dropped in `into_inner` which removes the socket
  31. /// reference. This properly tracks the initialization state without any additional bytes as
  32. /// the `None` variant occupies the `0` pattern which is invalid for the reference.
  33. socket: Option<&'a mut T>,
  34. }
  35. impl<'a, T: Session + 'a> Ref<'a, T> {
  36. /// Wrap a pointer to a socket to make a smart pointer.
  37. ///
  38. /// Calling this function is only necessary if your code is using [into_inner].
  39. ///
  40. /// [into_inner]: #method.into_inner
  41. pub fn new(socket: &'a mut T) -> Self {
  42. Ref {
  43. socket: Some(socket),
  44. }
  45. }
  46. /// Unwrap a smart pointer to a socket.
  47. ///
  48. /// The finalization code is not run. Prompt operation of the network stack depends
  49. /// on wrapping the returned pointer back and dropping it.
  50. ///
  51. /// Calling this function is only necessary to achieve composability if you *must*
  52. /// map a `&mut SocketRef<'a, XSocket>` to a `&'a mut XSocket` (note the lifetimes);
  53. /// be sure to call [new] afterwards.
  54. ///
  55. /// [new]: #method.new
  56. pub fn into_inner(mut ref_: Self) -> &'a mut T {
  57. ref_.socket.take().unwrap()
  58. }
  59. }
  60. impl<'a, T: Session> Deref for Ref<'a, T> {
  61. type Target = T;
  62. fn deref(&self) -> &Self::Target {
  63. // Deref is only used while the socket is still in place (into inner has not been called).
  64. self.socket.as_ref().unwrap()
  65. }
  66. }
  67. impl<'a, T: Session> DerefMut for Ref<'a, T> {
  68. fn deref_mut(&mut self) -> &mut Self::Target {
  69. self.socket.as_mut().unwrap()
  70. }
  71. }
  72. impl<'a, T: Session> Drop for Ref<'a, T> {
  73. fn drop(&mut self) {
  74. if let Some(socket) = self.socket.take() {
  75. Session::finish(socket);
  76. }
  77. }
  78. }