Skip to main content

varnish_sys/vcl/
subroutine.rs

1use crate::ffi::VCL_SUB;
2
3/// A wrapper around a [`VCL_SUB`] pointer representing a VCL subroutine.
4///
5/// Subroutines can be passed as arguments to VMOD functions and invoked via
6/// [`crate::vcl::Ctx::call_sub`] and [`crate::vcl::Ctx::check_call_sub`].
7#[derive(Debug, Clone, Copy)]
8pub struct Subroutine(pub(crate) VCL_SUB);
9
10impl Subroutine {
11    /// Return the underlying [`VCL_SUB`] pointer.
12    pub fn vcl_ptr(self) -> VCL_SUB {
13        self.0
14    }
15}
16
17macro_rules! define_subroutines {
18    (
19        subs {
20            $( ($sub_name:literal, $enum_id:ident, $bitmask_name:ident) )*
21        }
22        groups {
23            $( ($group_name:literal, $group_bitmask:ident, $group_ffi:ident, $is_method:ident) )*
24        }
25    ) => {
26        /// Valid scope names for the `#[restrict(...)]` attribute. Used by varnish-macros to validate inputs.
27        pub const VALID_RESTRICT_SCOPES: &[&str] = &[
28            $( $sub_name, )*
29            $( $group_name, )*
30        ];
31
32        pub mod bitmask {
33            ::paste::paste! {
34                pub use crate::ffi::{
35                    $( [<VCL_MET_ $bitmask_name>] as $bitmask_name, )*
36                    $( $group_ffi as $group_bitmask, )*
37                };
38            }
39        }
40
41        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
42        pub enum Id {
43            $( $enum_id, )*
44        }
45
46        /// Maps a `#[restrict(...)]` scope name to the exact bitmask constant identifier.
47        /// Used by varnish-macros codegen to avoid fragile string-manipulation heuristics.
48        pub fn bitmask_const_name(scope: &str) -> Option<&'static str> {
49            match scope {
50                $( $sub_name => Some(stringify!($bitmask_name)), )*
51                $( $group_name => Some(stringify!($group_bitmask)), )*
52                _ => None,
53            }
54        }
55
56        impl Id {
57            pub fn to_bitfield(self) -> u32 {
58                use bitmask::*;
59                match self {
60                    $( Id::$enum_id => $bitmask_name, )*
61                }
62            }
63
64            pub fn from_bitfield(val: u32) -> Option<Self> {
65                [$( Id::$enum_id, )*]
66                    .into_iter()
67                    .find(|id| id.to_bitfield() == val)
68            }
69
70            $(
71                pub fn $is_method(self) -> bool {
72                    self.to_bitfield() & bitmask::$group_bitmask != 0
73                }
74            )*
75
76            pub fn matches(self, mask: u32) -> bool {
77                self.to_bitfield() & mask != 0
78            }
79        }
80    };
81}
82
83define_subroutines! {
84    subs {
85        ("vcl_recv",             Recv,            RECV)
86        ("vcl_pipe",             Pipe,            PIPE)
87        ("vcl_pass",             Pass,            PASS)
88        ("vcl_hash",             Hash,            HASH)
89        ("vcl_purge",            Purge,           PURGE)
90        ("vcl_miss",             Miss,            MISS)
91        ("vcl_hit",              Hit,             HIT)
92        ("vcl_deliver",          Deliver,         DELIVER)
93        ("vcl_synth",            Synth,           SYNTH)
94        ("vcl_backend_fetch",    BackendFetch,    BACKEND_FETCH)
95        ("vcl_backend_refresh",  BackendRefresh,  BACKEND_REFRESH)
96        ("vcl_backend_response", BackendResponse, BACKEND_RESPONSE)
97        ("vcl_backend_error",    BackendError,    BACKEND_ERROR)
98        ("vcl_init",             Init,            INIT)
99        ("vcl_fini",             Fini,            FINI)
100    }
101    groups {
102        ("client",       CLIENT,       VCL_MET_TASK_C, is_client)
103        ("backend",      BACKEND,      VCL_MET_TASK_B, is_backend)
104        ("housekeeping", HOUSEKEEPING, VCL_MET_TASK_H, is_housekeeping)
105    }
106}