Skip to main content

vfsi_core/api/
metadata.rs

1//! Options shared by scalar convenience and vector metadata queries.
2
3#[bitfields::bitfield(u8)]
4#[derive(PartialEq, Eq)]
5struct AttrsFlags {
6    #[bits(default = true)]
7    follow: bool,
8    #[bits(7)]
9    _reserved: u8,
10}
11
12/// Select metadata fields and whether to follow the final symlink.
13/// Ancestor symlinks use ordinary backend path-resolution semantics.
14#[derive(Clone, Copy, Debug)]
15pub struct AttrsOptions {
16    fields: crate::api::Attributes,
17    flags: AttrsFlags,
18}
19impl Default for AttrsOptions {
20    fn default() -> Self {
21        Self {
22            fields: crate::api::Attributes::stat(),
23            flags: AttrsFlags::new(),
24        }
25    }
26}
27impl AttrsOptions {
28    /// Standard stat fields, following the final symlink.
29    pub fn new() -> Self {
30        Self::default()
31    }
32    /// Select requested attributes. Object type may additionally be fetched.
33    pub fn fields(mut self, fields: crate::api::Attributes) -> Self {
34        self.fields = fields;
35        self
36    }
37    /// Follow the final symlink when true; otherwise describe the link itself.
38    pub fn follow_symlinks(mut self, follow: bool) -> Self {
39        self.flags.set_follow(follow);
40        self
41    }
42    /// Requested attributes; unavailable optional attributes remain absent.
43    pub fn requested_attributes(self) -> crate::api::Attributes {
44        self.fields
45    }
46    /// Whether to follow the final component if it is a symlink.
47    pub fn follows_symlinks(self) -> bool {
48        self.flags.follow()
49    }
50}
51#[cfg(test)]
52mod option_layout_tests {
53    use super::*;
54    #[test]
55    fn packed_follow_flag_preserves_selected_fields() {
56        assert_eq!(std::mem::size_of::<AttrsFlags>(), 1);
57        assert!(AttrsOptions::default().follows_symlinks());
58        let fields = crate::api::Attributes::SIZE | crate::api::Attributes::CHANGE;
59        let options = AttrsOptions::new().fields(fields);
60        for follow in [false, true, false] {
61            let changed = options.follow_symlinks(follow);
62            assert_eq!(changed.follows_symlinks(), follow);
63            assert_eq!(changed.requested_attributes(), fields);
64            assert!(options.follows_symlinks());
65        }
66    }
67}