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