blob: 60b6b8a35a1fc252b8ec42a553701800051e5e89 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use cml::error::Error;
use std::{fmt, str::FromStr};
/// Represents the set of features a CML file is compiled with. This struct can be
/// used to check whether a feature used in CML is enabled.
#[derive(Debug)]
pub struct FeatureSet(Vec<Feature>);
impl FeatureSet {
/// Create an empty FeatureSet.
pub fn empty() -> FeatureSet {
FeatureSet(Vec::new())
}
/// Tests whether `feature` is enabled.
pub fn has(&self, feature: &Feature) -> bool {
self.0.iter().find(|f| *f == feature).is_some()
}
/// Returns an `Err` if `feature` is not enabled.
pub fn check(&self, feature: Feature) -> Result<(), Error> {
if self.has(&feature) {
Ok(())
} else {
Err(Error::UnstableFeature(feature.to_string()))
}
}
}
impl From<Vec<Feature>> for FeatureSet {
fn from(features: Vec<Feature>) -> FeatureSet {
FeatureSet(features)
}
}
/// A feature that can be enabled/opt-into.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Feature {
/// Enables unified services support in CML.
Services,
}
impl FromStr for Feature {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"services" => Ok(Feature::Services),
_ => Err(format!("unrecognized feature \"{}\"", s)),
}
}
}
impl fmt::Display for Feature {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str(match self {
Feature::Services => "services",
})
}
}
#[cfg(test)]
mod tests {
use {super::*, matches::assert_matches};
#[test]
fn feature_is_parsed() {
assert_eq!(Feature::Services, "services".parse::<Feature>().unwrap());
}
#[test]
fn feature_is_printed() {
assert_eq!("services", Feature::Services.to_string());
}
#[test]
fn feature_set_has() {
let set = FeatureSet::empty();
assert!(!set.has(&Feature::Services));
let set = FeatureSet::from(vec![Feature::Services]);
assert!(set.has(&Feature::Services));
}
#[test]
fn feature_set_check() {
let set = FeatureSet::empty();
assert_matches!(set.check(Feature::Services), Err(Error::UnstableFeature(f)) if f == "services");
let set = FeatureSet::from(vec![Feature::Services]);
assert_matches!(set.check(Feature::Services), Ok(()));
}
}