nydus_builder/core/
feature.rs

1// Copyright (C) 2022 Nydus Developers. All rights reserved.
2//
3// SPDX-License-Identifier: Apache-2.0
4
5use std::collections::HashSet;
6use std::convert::TryFrom;
7
8use anyhow::{bail, Result};
9
10const ERR_UNSUPPORTED_FEATURE: &str = "unsupported feature";
11
12/// Feature flags to control behavior of RAFS filesystem builder.
13#[derive(Clone, Debug, Hash, PartialEq, Eq)]
14pub enum Feature {
15    /// Append a Table Of Content footer to RAFS v6 data blob, to help locate data sections.
16    BlobToc,
17}
18
19impl TryFrom<&str> for Feature {
20    type Error = anyhow::Error;
21
22    fn try_from(f: &str) -> Result<Self> {
23        match f {
24            "blob-toc" => Ok(Self::BlobToc),
25            _ => bail!(
26                "{} `{}`, please try upgrading to the latest nydus-image",
27                ERR_UNSUPPORTED_FEATURE,
28                f,
29            ),
30        }
31    }
32}
33
34/// A set of enabled feature flags to control behavior of RAFS filesystem builder
35#[derive(Clone, Debug)]
36pub struct Features(HashSet<Feature>);
37
38impl Default for Features {
39    fn default() -> Self {
40        Self::new()
41    }
42}
43
44impl Features {
45    /// Create a new instance of [Features].
46    pub fn new() -> Self {
47        Self(HashSet::new())
48    }
49
50    /// Check whether a feature is enabled or not.
51    pub fn is_enabled(&self, feature: Feature) -> bool {
52        self.0.contains(&feature)
53    }
54}
55
56impl TryFrom<&str> for Features {
57    type Error = anyhow::Error;
58
59    fn try_from(features: &str) -> Result<Self> {
60        let mut list = Features::new();
61        for feat in features.trim().split(',') {
62            if !feat.is_empty() {
63                let feature = Feature::try_from(feat.trim())?;
64                list.0.insert(feature);
65            }
66        }
67        Ok(list)
68    }
69}
70
71#[cfg(test)]
72mod tests {
73    use super::*;
74
75    #[test]
76    fn test_feature() {
77        assert_eq!(Feature::try_from("blob-toc").unwrap(), Feature::BlobToc);
78        Feature::try_from("unknown-feature-bit").unwrap_err();
79    }
80
81    #[test]
82    fn test_features() {
83        let features = Features::try_from("blob-toc").unwrap();
84        assert!(features.is_enabled(Feature::BlobToc));
85        let features = Features::try_from("blob-toc,").unwrap();
86        assert!(features.is_enabled(Feature::BlobToc));
87        let features = Features::try_from("blob-toc, ").unwrap();
88        assert!(features.is_enabled(Feature::BlobToc));
89        let features = Features::try_from("blob-toc ").unwrap();
90        assert!(features.is_enabled(Feature::BlobToc));
91        let features = Features::try_from(" blob-toc ").unwrap();
92        assert!(features.is_enabled(Feature::BlobToc));
93    }
94}