ci-cargo

CI for Rust code.
git clone https://git.philomathiclife.com/repos/ci-cargo
Log | Files | Refs | README

manifest.rs (157834B)


      1 use super::{
      2     args::NonZeroUsizePlus1,
      3     cargo::{Toolchain, ToolchainErr},
      4 };
      5 use alloc::borrow::Cow;
      6 use core::cmp::Ordering;
      7 use std::{
      8     fs::{File, TryLockError},
      9     io::{Error, ErrorKind, Read as _, StderrLock, Write as _},
     10     path::{Path, PathBuf},
     11 };
     12 use toml::{
     13     Spanned,
     14     de::{DeArray, DeValue, Error as TomlErr},
     15     map::Map,
     16 };
     17 /// `"workspace"`.
     18 const WORKSPACE: &str = "workspace";
     19 /// `"package"`.
     20 const PACKAGE: &str = "package";
     21 /// `"rust-version"`.
     22 const RUST_VERSION: &str = "rust-version";
     23 /// Error returned from extracting `"workspace"`.
     24 #[cfg_attr(test, derive(Debug, PartialEq))]
     25 #[derive(Clone, Copy)]
     26 pub(crate) enum WorkspaceErr {
     27     /// Variant returned when there is no `"workspace"` key.
     28     Missing,
     29     /// Variant returned when `"workspace"` is not a table.
     30     InvalidType,
     31     /// Variant returned when `workspace.package` does not exist.
     32     MissingPackage,
     33     /// Variant returned when `workspace.package` is not a table.
     34     InvalidPackageType,
     35     /// Variant returned when `workspace.package.rust-version` does not exist.
     36     MissingPackageMsrv,
     37     /// Variant returned when `workspace.package.rust-version` is not a string.
     38     InvalidPackageMsrvType,
     39     /// Variant returned when `workspace.package.rust-version` is not a valid MSRV.
     40     Msrv,
     41 }
     42 impl WorkspaceErr {
     43     /// Writes `self` to `stderr`.
     44     fn write(self, mut stderr: StderrLock<'_>, file: &Path) -> Result<(), Error> {
     45         match self {
     46             Self::Missing => writeln!(
     47                 stderr,
     48                 "'{WORKSPACE}' does not exist in {}.",
     49                 file.display()
     50             ),
     51             Self::InvalidType => writeln!(
     52                 stderr,
     53                 "'{WORKSPACE}' exists but is not a table in {}.",
     54                 file.display()
     55             ),
     56             Self::MissingPackage => writeln!(
     57                 stderr,
     58                 "'{WORKSPACE}.{PACKAGE}' does not exist in {}.",
     59                 file.display()
     60             ),
     61             Self::InvalidPackageType => writeln!(
     62                 stderr,
     63                 "'{WORKSPACE}.{PACKAGE}' exists but is not a table in {}.",
     64                 file.display()
     65             ),
     66             Self::MissingPackageMsrv => writeln!(
     67                 stderr,
     68                 "'{WORKSPACE}.{PACKAGE}.{RUST_VERSION}' does not exist in {}.",
     69                 file.display()
     70             ),
     71             Self::InvalidPackageMsrvType => writeln!(
     72                 stderr,
     73                 "'{WORKSPACE}.{PACKAGE}.{RUST_VERSION}' exists but is not a string in {}.",
     74                 file.display()
     75             ),
     76             Self::Msrv => writeln!(
     77                 stderr,
     78                 "'{WORKSPACE}.{PACKAGE}.{RUST_VERSION}' exists but is not a valid MSRV in {}.",
     79                 file.display()
     80             ),
     81         }
     82     }
     83 }
     84 /// `"name"`.
     85 const NAME: &str = "name";
     86 /// Error returned from extracting `"package"`.
     87 #[cfg_attr(test, derive(Debug))]
     88 pub(crate) enum PackageErr {
     89     /// Variant returned when there is no `"package"` key.
     90     Missing,
     91     /// Variant returned when `"package"` is not a table.
     92     InvalidType,
     93     /// Variant returned when `packagen.name` does not exist.
     94     MissingName,
     95     /// Variant returned when `package.name` is not a string.
     96     InvalidNameType,
     97     /// Variant returned when `package.rust-version` is not a string nor table.
     98     InvalidMsrvType,
     99     /// Variant returned when `package.rust-version` is not a valid MSRV.
    100     Msrv,
    101     /// Variant returned when `package.rust-version` is table that doesn't contain the `"workspace"` key.
    102     MsrvWorkspaceMissing,
    103     /// Variant returned when `package.rust-version.workspace` is not a Boolean with value `true`.
    104     MsrvWorkspaceVal,
    105     /// Variant returned when `package.workspace` is not a string.
    106     InvalidWorkspaceType,
    107     /// Variant returned when searching for the workspace file errors.
    108     WorkspaceIo(Error),
    109     /// Variant when locking the workspace file errors.
    110     WorkspaceLock(TryLockError),
    111     /// Variant when the length of the workspace file does not match the length reported from the file system.
    112     WorkspaceLenMismatch,
    113     /// Variant returned when there is no workspace `Cargo.toml`.
    114     ///
    115     /// This is only returned if the package's MSRV is inherited from the workspace, there is no
    116     /// `workspace` key in the package's `Cargo.toml`, and there is no `workspace` key in the table
    117     /// `package` (i.e., this is only returned when we must search for it by crawling up the directory).
    118     WorkspaceDoesNotExist,
    119     /// Variant returned when the file located at `package.workspace` could not be read.
    120     ///
    121     /// This is only returned if the table `package` had a key `workspace` that was a string, or we searched
    122     /// for the workspace and found a `Cargo.toml`.
    123     WorkspaceRead(Error, PathBuf),
    124     /// Variant returned when the file located at `package.workspace` could not be locked.
    125     ///
    126     /// This is only returned if the table `package` had a key `workspace` that was a string, or we searched
    127     /// for the workspace and found a `Cargo.toml`.
    128     WorkspaceReadLock(TryLockError, PathBuf),
    129     /// Variant returned when the length of the file located at `package.workspace` does not match the length
    130     /// reported by the file system.
    131     ///
    132     /// This is only returned if the table `package` had a key `workspace` that was a string, or we searched
    133     /// for the workspace and found a `Cargo.toml`.
    134     WorkspaceReadLenMismatch(PathBuf),
    135     /// Variant returned when the file located at `package.workspace` is not valid TOML.
    136     ///
    137     /// This is only returned if the table `package` had a key `workspace` that was a string, or we searched
    138     /// for the workspace and found a `Cargo.toml`.
    139     WorkspaceToml(TomlErr, PathBuf),
    140     /// Variant returned when `package.rust-version` defers to the workspace MSRV, but there was an error
    141     /// extracting the workspace MSRV from the file located at the contained `PathBuf`.
    142     Workspace(WorkspaceErr, PathBuf),
    143 }
    144 impl PackageErr {
    145     /// Writes `self` to `stderr`.
    146     #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
    147     fn write(self, mut stderr: StderrLock<'_>, file: &Path) -> Result<(), Error> {
    148         match self {
    149             Self::Missing => writeln!(stderr, "'{PACKAGE}' does not exist in {}.", file.display()),
    150             Self::InvalidType => writeln!(
    151                 stderr,
    152                 "'{PACKAGE}' exists but is not a table in {}.",
    153                 file.display()
    154             ),
    155             Self::MissingName => writeln!(stderr, "'{PACKAGE}.{NAME}' does not exist in {}.", file.display()),
    156             Self::InvalidNameType => writeln!(
    157                 stderr,
    158                 "'{PACKAGE}.{NAME}' exists but is not a string in {}.",
    159                 file.display()
    160             ),
    161             Self::InvalidMsrvType => writeln!(
    162                 stderr,
    163                 "'{PACKAGE}.{RUST_VERSION}' exists but is not a string nor table in {}.",
    164                 file.display()
    165             ),
    166             Self::Msrv => writeln!(
    167                 stderr,
    168                 "'{PACKAGE}.{RUST_VERSION}' is a string but is not a valid MSRV in {}.",
    169                 file.display()
    170             ),
    171             Self::MsrvWorkspaceMissing => writeln!(
    172                 stderr,
    173                 "'{PACKAGE}.{RUST_VERSION}' is a table but does not contain the key '{WORKSPACE}' in {}.",
    174                 file.display()
    175             ),
    176             Self::MsrvWorkspaceVal => writeln!(
    177                 stderr,
    178                 "'{PACKAGE}.{RUST_VERSION}.{WORKSPACE}' exists but is not a Boolean or is not true in {}.",
    179                 file.display()
    180             ),
    181             Self::WorkspaceIo(e) => writeln!(
    182                 stderr,
    183                 "There was an error looking for the workspace Cargo.toml in {} and its ancestor directories: {e}.",
    184                 file.parent().unwrap_or_else(|| unreachable!("there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.")).display(),
    185             ),
    186             Self::WorkspaceLock(e) => writeln!(
    187                 stderr,
    188                 "There was an error locking the workspace Cargo.toml in {} and its ancestor directories: {e}.",
    189                 file.parent().unwrap_or_else(|| unreachable!("there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.")).display(),
    190             ),
    191             Self::WorkspaceLenMismatch=> writeln!(
    192                 stderr,
    193                 "The length of the workspace Cargo.toml in {} does not match the length reported by the file systemn.",
    194                 file.parent().unwrap_or_else(|| unreachable!("there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.")).display(),
    195             ),
    196             Self::WorkspaceDoesNotExist => writeln!(
    197                 stderr,
    198                 "There is no workspace Cargo.toml in {} nor its ancestor directories.",
    199                 file.parent().unwrap_or_else(|| unreachable!("there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.")).display(),
    200             ),
    201             Self::InvalidWorkspaceType => writeln!(
    202                 stderr,
    203                 "'{PACKAGE}.{WORKSPACE}' exists but is not a string in {}.",
    204                 file.display()
    205             ),
    206             Self::WorkspaceRead(e, p) => {
    207                 writeln!(stderr, "There was an issue reading the workspace file {}: {e}.", p.display())
    208             }
    209             Self::WorkspaceReadLock(e, p) => {
    210                 writeln!(stderr, "There was an issue locking the workspace file {}: {e}.", p.display())
    211             }
    212             Self::WorkspaceReadLenMismatch(p) => {
    213                 writeln!(stderr, "The length of the workspace file {} does not match the length reported by the file system.", p.display())
    214             }
    215             Self::WorkspaceToml(e, p) => write!(
    216                 stderr,
    217                 "Error parsing workspace file {} as TOML: {e}.",
    218                 p.display()
    219             ),
    220             Self::Workspace(e, p) => e.write(stderr, &p),
    221         }
    222     }
    223 }
    224 /// `"features"`.
    225 const FEATURES: &str = "features";
    226 /// Error returned from extracting feature dependencies.
    227 #[cfg_attr(test, derive(Debug, PartialEq))]
    228 pub(crate) enum FeatureDependenciesErr {
    229     /// Variant returned when a feature is not an array.
    230     ///
    231     /// The contained `String` is the name of the feature.
    232     InvalidFeatureType(String),
    233     /// Variant returned when a feature dependency is not a string.
    234     ///
    235     /// The contained `String` is the name of the feature.
    236     InvalidDependencyType(String),
    237     /// Variant returned when a feature dependency is not a feature nor dependency.
    238     ///
    239     /// The first contained `String` is the name of the feature, and the second `String` is the name of the invalid
    240     /// feature dependency.
    241     ///
    242     /// Note this is only possible when `allow_implied_features` is `false` when passed to
    243     /// [`Features::validate_dependencies`].
    244     InvalidDependency(String, String),
    245     /// Variant returned when a feature is cyclic.
    246     ///
    247     /// The contained `String` is the name of the feature.
    248     CyclicFeature(String),
    249     /// Variant returned when a feature dependency is redundant.
    250     ///
    251     /// The first contained `String` is the name of the feature, and the second `String` is the name of the
    252     /// redundant feature dependency.
    253     RedundantDependency(String, String),
    254 }
    255 impl FeatureDependenciesErr {
    256     /// Writes `self` to `stderr`.
    257     fn write(self, mut stderr: StderrLock<'_>, file: &Path) -> Result<(), Error> {
    258         match self {
    259             Self::InvalidFeatureType(name) => {
    260                 writeln!(
    261                     stderr,
    262                     "'{FEATURES}.{name}' is not an array in {}.",
    263                     file.display()
    264                 )
    265             }
    266             Self::InvalidDependencyType(name) => writeln!(
    267                 stderr,
    268                 "'{FEATURES}.{name}' contains a value that is not a string in {}.",
    269                 file.display()
    270             ),
    271             Self::InvalidDependency(name, dep_name) => writeln!(
    272                 stderr,
    273                 "'{FEATURES}.{name}' contains '{dep_name}' which is neither a feature nor dependency in {}. It may be an implied feature from an optional dependency, but --allow-implied-features was not passed.",
    274                 file.display()
    275             ),
    276             Self::CyclicFeature(name) => writeln!(
    277                 stderr,
    278                 "'{FEATURES}.{name}' is a cyclic feature in {}.",
    279                 file.display()
    280             ),
    281             Self::RedundantDependency(name, dep_name) => writeln!(
    282                 stderr,
    283                 "'{FEATURES}.{name}' contains the redundant dependency '{dep_name}' in {}.",
    284                 file.display()
    285             ),
    286         }
    287     }
    288 }
    289 /// Error returned from extracting `"features"`.
    290 #[cfg_attr(test, derive(Debug, PartialEq))]
    291 pub(crate) enum FeaturesErr {
    292     /// Variant returned when `features` is not a table in Cargo.toml.
    293     InvalidType,
    294     /// Variant returned when `features` contains a feature with an invalid name.
    295     ///
    296     /// The contained `String` is the name of the feature.
    297     InvalidName(String),
    298     /// Variant returned when there is an issue with a feature's dependencies.
    299     FeatureDependencies(FeatureDependenciesErr),
    300 }
    301 impl FeaturesErr {
    302     /// Writes `self` to `stderr`.
    303     fn write(self, mut stderr: StderrLock<'_>, file: &Path) -> Result<(), Error> {
    304         match self {
    305             Self::InvalidType => {
    306                 writeln!(
    307                     stderr,
    308                     "'{FEATURES}' exists but is not a table in {}.",
    309                     file.display()
    310                 )
    311             }
    312             Self::InvalidName(name) => {
    313                 writeln!(
    314                     stderr,
    315                     "'{FEATURES}.{name}' is not a valid feature name in {}.",
    316                     file.display()
    317                 )
    318             }
    319             Self::FeatureDependencies(e) => e.write(stderr, file),
    320         }
    321     }
    322 }
    323 /// Error returned from extracting dependencies.
    324 #[cfg_attr(test, derive(Debug, PartialEq))]
    325 pub(crate) enum DependenciesErr {
    326     /// Variant returned when the dependencies is not a table.
    327     ///
    328     /// The contained `str` is the name of the dependencies (e.g., `"dependencies"`).
    329     Type(&'static str),
    330     /// Variant returned when a dependency has an invalid name.
    331     ///
    332     /// The contained `str` is the name of dependencies (e.g., `"dependencies"`), and the `String` is the
    333     /// name of the dependency.
    334     Name(&'static str, String),
    335     /// Variant returned when a dependency is not a string or table.
    336     ///
    337     /// The contained `str` is the name of dependencies (e.g., `"dependencies"`), and the `String` is the
    338     /// name of the dependency.
    339     DependencyType(&'static str, String),
    340     /// Variant returned when a dependency contains an `"optional"` key whose value is not a Boolean.
    341     ///
    342     /// The contained `str` is the name of dependencies (e.g., `"dependencies"`), and the `String` is the
    343     /// name of the dependency.
    344     OptionalType(&'static str, String),
    345     /// Variant returned when an optional dependency would cause an implied feature to be created.
    346     ///
    347     /// Note this is only possible when `allow_implied_features` is `false` when passed to
    348     /// [`Features::add_optional_dependencies`].
    349     ///
    350     /// The contained `str` is the name of dependencies (e.g., `"dependencies"`), and the `String` is the
    351     /// name of the dependency.
    352     ImpliedFeature(&'static str, String),
    353 }
    354 /// Error returned from extracting dependencies to add implied features.
    355 #[cfg_attr(test, derive(Debug, PartialEq))]
    356 pub(crate) enum ImpliedFeaturesErr {
    357     /// Variant returned from extracting dependencies.
    358     Dependencies(DependenciesErr),
    359     /// Variant returned when `target` is not a table in Cargo.toml.
    360     TargetType,
    361     /// Variant returned when `target` contains a key whose value is not a table.
    362     ///
    363     /// The contained `String` is the name of the key.
    364     TargetPlatformType(String),
    365     /// Variant returned when a target platform contains an issue with dependencies.
    366     ///
    367     /// The contained `String` is the name of the target platform.
    368     TagetPlatformDependencies(String, DependenciesErr),
    369     /// Variant returned when a feature dependency is not a feature nor dependency.
    370     ///
    371     /// The first contained `String` is the name of the feature, and the second `String` is the name of the invalid
    372     /// feature dependency.
    373     ///
    374     /// Note this is only possible when `allow_implied_features` is `true` when passed to
    375     /// [`Features::validate_dependencies`] since when `false` we verify the the dependency
    376     /// is defined as a feature.
    377     InvalidDependency(String, String),
    378 }
    379 /// `"optional"`.
    380 const OPTIONAL: &str = "optional";
    381 /// `"target"`.
    382 const TARGET: &str = "target";
    383 impl ImpliedFeaturesErr {
    384     /// Writes `self` to `stderr`.
    385     fn write(self, mut stderr: StderrLock<'_>, file: &Path) -> Result<(), Error> {
    386         match self {
    387             Self::Dependencies(e) => match e {
    388                 DependenciesErr::Type(name) => {
    389                     writeln!(
    390                         stderr,
    391                         "'{name}' exists but is not a table in {}.",
    392                         file.display()
    393                     )
    394                 }
    395                 DependenciesErr::Name(name, dep_name) => {
    396                     writeln!(
    397                         stderr,
    398                         "'{name}.{dep_name}' is not a valid dependency name in {}.",
    399                         file.display()
    400                     )
    401                 }
    402                 DependenciesErr::DependencyType(name, dep_name) => {
    403                     writeln!(
    404                         stderr,
    405                         "'{name}.{dep_name}' exists but is not a string nor table in {}.",
    406                         file.display()
    407                     )
    408                 }
    409                 DependenciesErr::OptionalType(name, dep_name) => {
    410                     writeln!(
    411                         stderr,
    412                         "'{name}.{dep_name}.{OPTIONAL}' exists but is not a Boolean in {}.",
    413                         file.display()
    414                     )
    415                 }
    416                 DependenciesErr::ImpliedFeature(name, dep_name) => {
    417                     writeln!(
    418                         stderr,
    419                         "'{name}.{dep_name}' causes an implied feature to be defined in {}, but implied features were forbidden. --allow-implied-features can be passed to allow it.",
    420                         file.display()
    421                     )
    422                 }
    423             },
    424             Self::TargetType => {
    425                 writeln!(
    426                     stderr,
    427                     "'{TARGET}' exists but is not a table in {}.",
    428                     file.display()
    429                 )
    430             }
    431             Self::TargetPlatformType(name) => {
    432                 writeln!(
    433                     stderr,
    434                     "'{TARGET}.{name}' exists but is not a table in {}.",
    435                     file.display()
    436                 )
    437             }
    438             Self::TagetPlatformDependencies(name, e) => match e {
    439                 DependenciesErr::Type(table_name) => {
    440                     writeln!(
    441                         stderr,
    442                         "'{TARGET}.{name}.{table_name}' exists but is not a table in {}.",
    443                         file.display()
    444                     )
    445                 }
    446                 DependenciesErr::Name(table_name, dep_name) => {
    447                     writeln!(
    448                         stderr,
    449                         "'{TARGET}.{name}.{table_name}.{dep_name}' is not a valid dependency name in {}.",
    450                         file.display()
    451                     )
    452                 }
    453                 DependenciesErr::DependencyType(table_name, dep_name) => writeln!(
    454                     stderr,
    455                     "'{TARGET}.{name}.{table_name}.{dep_name}' exists but is not a string nor table in {}.",
    456                     file.display()
    457                 ),
    458                 DependenciesErr::OptionalType(table_name, dep_name) => writeln!(
    459                     stderr,
    460                     "'{TARGET}.{name}.{table_name}.{dep_name}.{OPTIONAL}' exists but is not a Boolean in {}.",
    461                     file.display()
    462                 ),
    463                 DependenciesErr::ImpliedFeature(table_name, dep_name) => {
    464                     writeln!(
    465                         stderr,
    466                         "'{TARGET}.{name}.{table_name}.{dep_name}' causes an implied feature to be defined in {}, but implied features were forbidden. --allow-implied-features can be passed to allow it.",
    467                         file.display()
    468                     )
    469                 }
    470             },
    471             Self::InvalidDependency(name, dep_name) => writeln!(
    472                 stderr,
    473                 "'{FEATURES}.{name}' contains '{dep_name}' which is neither a feature nor dependency in {}.",
    474                 file.display()
    475             ),
    476         }
    477     }
    478 }
    479 /// Error returned from parsing Cargo.toml.
    480 #[cfg_attr(test, derive(Debug, PartialEq))]
    481 pub(crate) enum ManifestErr {
    482     /// Variant returned when Cargo.toml is not valid TOML.
    483     Toml(TomlErr, PathBuf),
    484     /// Variant returned when extracting `package`.
    485     Package(PackageErr, PathBuf),
    486     /// Variant returned when extracting `features`.
    487     Features(FeaturesErr, PathBuf),
    488     /// Variant returned when extracting dependencies in order to add implied features.
    489     ImpliedFeatures(ImpliedFeaturesErr, PathBuf),
    490     /// Variant returned when ignoring a feature that does not exist.
    491     UndefinedIgnoreFeature(String, PathBuf),
    492 }
    493 impl ManifestErr {
    494     /// Writes `self` to `stderr`.
    495     pub(crate) fn write(self, mut stderr: StderrLock<'_>) -> Result<(), Error> {
    496         match self {
    497             Self::Toml(e, file) => write!(
    498                 stderr,
    499                 "Error parsing package file {} as TOML: {e}.",
    500                 file.display()
    501             ),
    502             Self::Package(e, file) => e.write(stderr, &file),
    503             Self::Features(e, file) => e.write(stderr, &file),
    504             Self::ImpliedFeatures(e, file) => e.write(stderr, &file),
    505             Self::UndefinedIgnoreFeature(feature, file) => writeln!(
    506                 stderr,
    507                 "The feature '{feature}' was requested to be ignored, but it is not a feature in the package file {}.",
    508                 file.display()
    509             ),
    510         }
    511     }
    512 }
    513 /// Error when there are too many features to create the power set.
    514 #[cfg_attr(test, derive(Debug, PartialEq))]
    515 pub(crate) struct TooManyFeaturesErr;
    516 /// Parses `val` as a `u64` in decimal notation without leading 0s.
    517 ///
    518 /// # Errors
    519 ///
    520 /// Errors iff `val` is not a valid `u64` in decimal notation without leading 0s.
    521 pub(crate) fn parse_int(val: &str) -> Result<u64, ()> {
    522     val.as_bytes().first().ok_or(()).and_then(|fst| {
    523         if *fst == b'0' {
    524             if val.len() == 1 { Ok(0) } else { Err(()) }
    525         } else {
    526             val.parse().map_err(|_e| ())
    527         }
    528     })
    529 }
    530 /// MSRV in Cargo.toml.
    531 #[cfg_attr(test, derive(Debug, PartialEq))]
    532 pub(crate) struct Msrv {
    533     /// Major version.
    534     major: u64,
    535     /// Minor version.
    536     minor: Option<u64>,
    537     /// Patch version.
    538     patch: Option<u64>,
    539 }
    540 impl Msrv {
    541     /// Converts `msrv` into `Self` based on a valid MSRV string.
    542     #[expect(unsafe_code, reason = "comments justify their correctness")]
    543     fn extract_msrv(msrv: &str) -> Result<Self, ()> {
    544         let mut iter = msrv.as_bytes().split(|b| *b == b'.');
    545         iter.next().ok_or(()).and_then(|fst| {
    546             // SAFETY:
    547             // The original input is a `str` and we split on `b'.'` which is a single-byte
    548             // UTF-8 code unit; thus we don't have to worry about splitting a multi-byte
    549             // UTF-8 code unit.
    550             let major_utf8 = unsafe { str::from_utf8_unchecked(fst) };
    551             parse_int(major_utf8).and_then(|major| {
    552                 iter.next().map_or_else(
    553                     || {
    554                         Ok(Self {
    555                             major,
    556                             minor: None,
    557                             patch: None,
    558                         })
    559                     },
    560                     |snd| {
    561                         // SAFETY:
    562                         // The original input is a `str` and we split on `b'.'` which is
    563                         // a single-byte UTF-8 code unit; thus we don't have to worry
    564                         // about splitting a multi-byte UTF-8 code unit.
    565                         let minor_utf8 = unsafe { str::from_utf8_unchecked(snd) };
    566                         parse_int(minor_utf8).and_then(|minor_val| {
    567                             iter.next().map_or_else(
    568                                 || {
    569                                     Ok(Self {
    570                                         major,
    571                                         minor: Some(minor_val),
    572                                         patch: None,
    573                                     })
    574                                 },
    575                                 |lst| {
    576                                     // SAFETY:
    577                                     // The original input is a `str` and we split on
    578                                     // `b'.'` which is a single-byte UTF-8 code
    579                                     // unit; thus we don't have to worry about
    580                                     // splitting a multi-byte UTF-8 code unit.
    581                                     let patch_utf8 = unsafe { str::from_utf8_unchecked(lst) };
    582                                     parse_int(patch_utf8).and_then(|patch_val| {
    583                                         iter.next().map_or_else(
    584                                             || {
    585                                                 Ok(Self {
    586                                                     major,
    587                                                     minor: Some(minor_val),
    588                                                     patch: Some(patch_val),
    589                                                 })
    590                                             },
    591                                             |_| Err(()),
    592                                         )
    593                                     })
    594                                 },
    595                             )
    596                         })
    597                     },
    598                 )
    599             })
    600         })
    601     }
    602     /// Reads `workspace` from `toml` extracting the MSRV.
    603     fn extract_workspace(
    604         toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
    605     ) -> Result<Self, WorkspaceErr> {
    606         toml.get(WORKSPACE)
    607             .ok_or(WorkspaceErr::Missing)
    608             .and_then(|work_span| {
    609                 if let DeValue::Table(ref workspace) = *work_span.get_ref() {
    610                     workspace
    611                         .get(PACKAGE)
    612                         .ok_or(WorkspaceErr::MissingPackage)
    613                         .and_then(|pack_span| {
    614                             if let DeValue::Table(ref package) = *pack_span.get_ref() {
    615                                 package
    616                                     .get(RUST_VERSION)
    617                                     .ok_or(WorkspaceErr::MissingPackageMsrv)
    618                                     .and_then(|msrv_span| {
    619                                         if let DeValue::String(ref msrv) = *msrv_span.get_ref() {
    620                                             Self::extract_msrv(msrv)
    621                                                 .map_err(|()| WorkspaceErr::Msrv)
    622                                         } else {
    623                                             Err(WorkspaceErr::InvalidPackageMsrvType)
    624                                         }
    625                                     })
    626                             } else {
    627                                 Err(WorkspaceErr::InvalidPackageType)
    628                             }
    629                         })
    630                 } else {
    631                     Err(WorkspaceErr::InvalidType)
    632                 }
    633             })
    634     }
    635     /// Recursively looks for `Cargo.toml` in `cur_dir` and ancestor directories until one is found
    636     /// that contains a key named [`WORKSPACE`]. Once found, it's MSRV will be parsed and returned.
    637     ///
    638     /// We make this recursive in case the (impossible?) path traversal becomes cyclic; in which
    639     /// we want a stack overflow to occur.
    640     ///
    641     /// Note if any error occurs not related to a not found file error, then this will error.
    642     #[expect(
    643         clippy::verbose_file_reads,
    644         reason = "false positive since we want to lock the file"
    645     )]
    646     fn get_workspace_toml(mut cur_dir: PathBuf) -> Result<Self, PackageErr> {
    647         cur_dir.push(super::cargo_toml());
    648         match File::options()
    649             .read(true)
    650             .open(&cur_dir)
    651         {
    652             Ok(mut file) => {
    653                 file.try_lock_shared()
    654                     .map_err(PackageErr::WorkspaceLock)
    655                     .and_then(|()| {
    656                         file.metadata()
    657                             .map_err(PackageErr::WorkspaceIo)
    658                             .and_then(|meta| {
    659                                 let meta_len = usize::try_from(meta.len()).unwrap_or(usize::MAX);
    660                                 let mut data_utf8 = Vec::with_capacity(meta_len);
    661                                 file.read_to_end(&mut data_utf8)
    662                                     .map_err(PackageErr::WorkspaceIo)
    663                                     .and_then(|len| {
    664                                         drop(file);
    665                                         if meta_len == len {
    666                                             String::from_utf8(data_utf8)
    667                                                 .map_err(|e| PackageErr::WorkspaceIo(Error::other(e)))
    668                                                 .and_then(|data| {
    669                                                     Map::parse(&data)
    670                                                         .map_err(|e| PackageErr::WorkspaceToml(e, cur_dir.clone()))
    671                                                         .and_then(|toml| {
    672                                                             let t = toml.into_inner();
    673                                                             if t.contains_key(WORKSPACE) {
    674                                                                 Self::extract_workspace(&t)
    675                                                                     .map_err(|e| PackageErr::Workspace(e, cur_dir))
    676                                                             } else {
    677                                                                 _ = cur_dir.pop();
    678                                                                 if cur_dir.pop() {
    679                                                                     Self::get_workspace_toml(cur_dir)
    680                                                                 } else {
    681                                                                     Err(PackageErr::WorkspaceDoesNotExist)
    682                                                                 }
    683                                                             }
    684                                                         })
    685                                                 })
    686                                         } else {
    687                                             Err(PackageErr::WorkspaceLenMismatch)
    688                                         }
    689                                     })
    690                             })
    691                     })
    692             }
    693             Err(e) => {
    694                 if matches!(e.kind(), ErrorKind::NotFound) {
    695                     _ = cur_dir.pop();
    696                     if cur_dir.pop() {
    697                         Self::get_workspace_toml(cur_dir)
    698                     } else {
    699                         Err(PackageErr::WorkspaceIo(e))
    700                     }
    701                 } else {
    702                     Err(PackageErr::WorkspaceIo(e))
    703                 }
    704             }
    705         }
    706     }
    707     /// Extracts `"rust-version"` from `"package"` or `toml` in the case it's defined in a workspace.
    708     #[expect(
    709         clippy::panic_in_result_fn,
    710         reason = "want to crash when there is a bug"
    711     )]
    712     #[expect(
    713         clippy::verbose_file_reads,
    714         reason = "false positive since we want to lock the file"
    715     )]
    716     fn extract_from_toml(
    717         toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
    718         package: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
    719         cargo_toml: &Path,
    720     ) -> Result<Option<Self>, PackageErr> {
    721         package.get(RUST_VERSION).map_or(Ok(None), |msrv_span| {
    722             match *msrv_span.get_ref() {
    723                 DeValue::String(ref msrv) => Self::extract_msrv(msrv)
    724                     .map_err(|()| PackageErr::Msrv)
    725                     .map(Some),
    726                 DeValue::Table(ref msrv) => msrv
    727                     .get(WORKSPACE)
    728                     .ok_or(PackageErr::MsrvWorkspaceMissing)
    729                     .and_then(|work| {
    730                         if matches!(*work.get_ref(), DeValue::Boolean(b) if b) {
    731                             package.get(WORKSPACE).map_or_else(
    732                                 || if toml.contains_key(WORKSPACE) {
    733                                     Self::extract_workspace(toml).map_err(|e| PackageErr::Workspace(e, cargo_toml.to_path_buf())).map(Some)
    734                                 } else {
    735                                     let mut search_path = cargo_toml.to_path_buf();
    736                                     assert!(search_path.pop(), "there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.");
    737                                     if search_path.pop() {
    738                                         Self::get_workspace_toml(search_path).map(Some)
    739                                     } else {
    740                                         Err(PackageErr::WorkspaceDoesNotExist)
    741                                     }
    742                                 },
    743                                 |path_span| {
    744                                     if let DeValue::String(ref workspace_path) = *path_span.get_ref() {
    745                                         let mut path = cargo_toml.to_path_buf();
    746                                         assert!(path.pop(), "there is a bug in main. manifest::Manifest::from_toml must be passed the absolute path to the package's Cargo.toml.");
    747                                         path.push(workspace_path.as_ref());
    748                                         path.push(super::cargo_toml());
    749                                         File::options().read(true).open(&path).map_err(|e| PackageErr::WorkspaceRead(e, path.clone())).and_then(|mut workspace_file| {
    750                                             workspace_file.try_lock_shared().map_err(|e| PackageErr::WorkspaceReadLock(e, path.clone())).and_then(|()| {
    751                                                 workspace_file.metadata().map_err(|e| PackageErr::WorkspaceRead(e, path.clone())).and_then(|meta| {
    752                                                     let meta_len = usize::try_from(meta.len()).unwrap_or(usize::MAX);
    753                                                     let mut workspace_utf8 = Vec::with_capacity(meta_len);
    754                                                     workspace_file.read_to_end(&mut workspace_utf8).map_err(|e| PackageErr::WorkspaceRead(e, path.clone())).and_then(|len| {
    755                                                         drop(workspace_file);
    756                                                         if meta_len == len {
    757                                                             String::from_utf8(workspace_utf8).map_err(|e| PackageErr::WorkspaceRead(Error::other(e), path.clone())).and_then(|workspace_data| {
    758                                                                 Map::parse(&workspace_data).map_err(|e| PackageErr::WorkspaceToml(e, path.clone())).and_then(|workspace_toml| Self::extract_workspace(workspace_toml.get_ref()).map_err(|e| PackageErr::Workspace(e, path)).map(Some))
    759                                                             })
    760                                                         } else {
    761                                                             Err(PackageErr::WorkspaceReadLenMismatch(path))
    762                                                         }
    763                                                     })
    764                                                 })
    765                                             })
    766                                         })
    767                                     } else {
    768                                         Err(PackageErr::InvalidWorkspaceType)
    769                                     }
    770                                 },
    771                             )
    772                         } else {
    773                             Err(PackageErr::MsrvWorkspaceVal)
    774                         }
    775                     }),
    776                 DeValue::Integer(_)
    777                 | DeValue::Float(_)
    778                 | DeValue::Boolean(_)
    779                 | DeValue::Datetime(_)
    780                 | DeValue::Array(_) => Err(PackageErr::InvalidMsrvType),
    781             }
    782         })
    783     }
    784     /// Returns `Some` containing the MSRV with `'+'` prepended iff `stable` is semantically greater than `self`
    785     /// or the default toolchan is semantically not equivalent to `self`; otherwise returns `None`.
    786     ///
    787     /// When `stable` is semantically less than the MSRV, an error is returned.
    788     pub(crate) fn compare_to_other(
    789         &self,
    790         default: bool,
    791         rustup_home: Option<&Path>,
    792         cargo_path: &Path,
    793         cargo_home: Option<&Path>,
    794     ) -> Result<Option<String>, Box<ToolchainErr>> {
    795         if default {
    796             Toolchain::Default(false)
    797         } else {
    798             Toolchain::Stable
    799         }
    800         .get_version(rustup_home, cargo_path, cargo_home)
    801         .and_then(|stable_dflt_version| {
    802             match self.major.cmp(&stable_dflt_version.major) {
    803                 Ordering::Less => Ok(true),
    804                 Ordering::Equal => self.minor.map_or_else(
    805                     || Ok(false),
    806                     |min| match min.cmp(&stable_dflt_version.minor) {
    807                         Ordering::Less => Ok(true),
    808                         Ordering::Equal => self.patch.map_or_else(
    809                             || Ok(false),
    810                             |pat| match pat.cmp(&stable_dflt_version.patch) {
    811                                 Ordering::Less => Ok(true),
    812                                 Ordering::Equal => Ok(false),
    813                                 Ordering::Greater => {
    814                                     if default {
    815                                         Ok(true)
    816                                     } else {
    817                                         Err(Box::new(ToolchainErr::MsrvTooHigh))
    818                                     }
    819                                 }
    820                             },
    821                         ),
    822                         Ordering::Greater => {
    823                             if default {
    824                                 Ok(true)
    825                             } else {
    826                                 Err(Box::new(ToolchainErr::MsrvTooHigh))
    827                             }
    828                         }
    829                     },
    830                 ),
    831                 Ordering::Greater => {
    832                     if default {
    833                         Ok(true)
    834                     } else {
    835                         Err(Box::new(ToolchainErr::MsrvTooHigh))
    836                     }
    837                 }
    838             }
    839             .and_then(|get_msrv| {
    840                 if get_msrv {
    841                     Toolchain::Msrv(&self.minor.map_or_else(
    842                         || format!("+{}", self.major),
    843                         |min| {
    844                             self.patch.map_or_else(
    845                                 || format!("+{}.{min}", self.major),
    846                                 |pat| format!("+{}.{min}.{pat}", self.major),
    847                             )
    848                         },
    849                     ))
    850                     .get_version(rustup_home, cargo_path, cargo_home)
    851                     .and_then(|msrv_version| {
    852                         if msrv_version.major == self.major
    853                             && self.minor.is_none_or(|minor| {
    854                                 msrv_version.minor == minor
    855                                     && self.patch.is_none_or(|patch| msrv_version.patch == patch)
    856                             })
    857                         {
    858                             Ok(Some(format!(
    859                                 "+{}.{}.{}",
    860                                 msrv_version.major, msrv_version.minor, msrv_version.patch
    861                             )))
    862                         } else {
    863                             Err(Box::new(ToolchainErr::MsrvNotCompatibleWithInstalledMsrv(
    864                                 msrv_version,
    865                             )))
    866                         }
    867                     })
    868                 } else {
    869                     Ok(None)
    870                 }
    871             })
    872         })
    873     }
    874 }
    875 /// `package` info.
    876 #[cfg_attr(test, derive(Debug, PartialEq))]
    877 pub(crate) struct Package {
    878     /// `rust-version`.
    879     msrv: Option<Msrv>,
    880     /// `name`.
    881     name: String,
    882 }
    883 impl Package {
    884     /// MSRV.
    885     pub(crate) const fn msrv(&self) -> Option<&Msrv> {
    886         self.msrv.as_ref()
    887     }
    888     /// Name.
    889     pub(crate) const fn name(&self) -> &str {
    890         self.name.as_str()
    891     }
    892     /// Extracts `"package"` from `toml`.
    893     fn extract_from_toml(
    894         toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
    895         cargo_toml: &Path,
    896     ) -> Result<Self, PackageErr> {
    897         toml.get(PACKAGE)
    898             .ok_or(PackageErr::Missing)
    899             .and_then(|pack_span| {
    900                 if let DeValue::Table(ref package) = *pack_span.get_ref() {
    901                     package
    902                         .get(NAME)
    903                         .ok_or(PackageErr::MissingName)
    904                         .and_then(|name_span| {
    905                             if let DeValue::String(ref name) = *name_span.get_ref() {
    906                                 Msrv::extract_from_toml(toml, package, cargo_toml).map(|msrv| {
    907                                     Self {
    908                                         msrv,
    909                                         name: name.clone().into_owned(),
    910                                     }
    911                                 })
    912                             } else {
    913                                 Err(PackageErr::InvalidNameType)
    914                             }
    915                         })
    916                 } else {
    917                     Err(PackageErr::InvalidType)
    918                 }
    919             })
    920     }
    921 }
    922 /// Returns `true` iff `nodes` is pairwise disconnected.
    923 #[expect(
    924     clippy::arithmetic_side_effects,
    925     clippy::indexing_slicing,
    926     reason = "comment justifies correctness"
    927 )]
    928 fn pairwise_disconnected(nodes: &[&str], features: &[(String, Vec<String>)]) -> bool {
    929     /// `panic`s with a static message about the existence of a bug in [`Manifest::deserialize`].
    930     #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
    931     fn impossible<T>() -> T {
    932         unreachable!(
    933             "there is a bug in manifest::Manifest::deserialize where feature dependencies are not only features."
    934         )
    935     }
    936     /// Returns `true` iff `feature_deps` directly contains `feature` or indirectly in the `Vec<String>`
    937     /// associated with it.
    938     fn contains(
    939         feature_deps: &[String],
    940         feature: &str,
    941         features: &[(String, Vec<String>)],
    942     ) -> bool {
    943         feature_deps.iter().any(|feat| {
    944             feat == feature
    945                 || contains(
    946                     &features
    947                         .iter()
    948                         .find(|val| val.0 == *feat)
    949                         .unwrap_or_else(impossible)
    950                         .1,
    951                     feature,
    952                     features,
    953                 )
    954         })
    955     }
    956     !nodes.iter().enumerate().any(|(idx, feature)| {
    957         let feature_info = &features
    958             .iter()
    959             .find(|val| val.0 == **feature)
    960             .unwrap_or_else(impossible)
    961             .1;
    962         // `idx < nodes.len()`, so overflow is not possible and indexing is fine.
    963         nodes[idx + 1..].iter().any(|feat| {
    964             contains(feature_info, feat, features)
    965                 || contains(
    966                     features
    967                         .iter()
    968                         .find(|val| val.0 == **feat)
    969                         .unwrap_or_else(impossible)
    970                         .1
    971                         .as_slice(),
    972                     feature,
    973                     features,
    974                 )
    975         })
    976     })
    977 }
    978 /// Power set of [`Features`] returned from [`Features::power_set`].
    979 ///
    980 /// Note this is technically not the power set of features since semantically equivalent sets are ignored.
    981 ///
    982 /// The last set iterated will always be the empty set. If no features in [`Features`] depend on another
    983 /// feature, then this will always return the entire set of features first; otherwise the entire set will
    984 /// never be returned. The expected cardinality of a set iterated decreases; thus while it will almost always
    985 /// be possible for a set _A_ to have larger cardinality than a set _B_ even when _A_ is iterated before _B_,
    986 /// the expected value is smaller.
    987 ///
    988 /// The reason we attempt, but don't guarantee, that the first set iterated corresponds to a semantically
    989 /// equivalent set as the original set is to take advantage of the parallel compiliation that occurs. Typically
    990 /// the more features one enables, the more dependencies and functionality is added. By compiling code that
    991 /// maximizes this first, we take better advantage of how code is compiled; in contrast if we compiled fewer
    992 /// features first, subsequent compilations with more features will have to happen. We don't guarantee this
    993 /// though since it slightly complicates code; instead we iterate based on the _expected_ cardinality in
    994 /// descending order.
    995 ///
    996 /// We don't implement `Iterator` since we want to re-use the same `String` that represents the set we are
    997 /// returning.
    998 #[cfg_attr(test, derive(Debug, PartialEq))]
    999 pub(crate) struct PowerSet<'a> {
   1000     /// The set of features.
   1001     feats: &'a [(String, Vec<String>)],
   1002     /// `true` iff there are more sets to iterate.
   1003     has_remaining: bool,
   1004     /// `true` iff `feats` has redundant features; thus requiring us to check if a given set should be returned.
   1005     check_overlap: bool,
   1006     /// The current element of the power set that we are to return.
   1007     ///
   1008     /// This gets decremented as we iterate sets.
   1009     idx: usize,
   1010     /// Intermediate buffer we use to check if a set contains redundant features.
   1011     buffer: Vec<&'a str>,
   1012     /// The set we return.
   1013     ///
   1014     /// This is of the form `"<feat_1>,<feat_2>,...,<feat_n>"`.
   1015     set: String,
   1016     /// Number of sets skipped due to an equivalence with a smaller set.
   1017     skipped_sets_counter: usize,
   1018     /// `true` iff they empty set should be skipped.
   1019     ///
   1020     /// This doesn't contribute to [`Self::skipped_sets_counter`].
   1021     skip_empty_set: bool,
   1022 }
   1023 impl<'a> PowerSet<'a> {
   1024     /// Max cardinality of a set we allow to take the power set of.
   1025     // usize::MAX = 2^usize::BITS - 1 >= usize::BITS since usize::MAX >= 0;
   1026     // thus `usize::BITS as usize` is free from truncation.
   1027     #[expect(clippy::as_conversions, reason = "comment justifies correctness")]
   1028     const MAX_SET_LEN: usize = usize::BITS as usize;
   1029     /// Returns the cardinality less one of the power set of a set
   1030     /// whose cardinality is `set_len`.
   1031     ///
   1032     /// `set_len` MUST not be greater than [`Self::MAX_SET_LEN`].
   1033     #[expect(
   1034         clippy::arithmetic_side_effects,
   1035         reason = "comment justifies correctness"
   1036     )]
   1037     const fn len_minus_one(set_len: usize) -> usize {
   1038         assert!(
   1039             set_len <= Self::MAX_SET_LEN,
   1040             "manifest::PowerSet::len_minus_one must be passed a `usize` no larger than PowerSet::MAX_SET_LEN"
   1041         );
   1042         if set_len == Self::MAX_SET_LEN {
   1043             usize::MAX
   1044         } else {
   1045             // We verified that `set_len <= usize::BITS`; thus
   1046             // this won't overflow nor underflow since 2^0 = 1.
   1047             (1 << set_len) - 1
   1048         }
   1049     }
   1050     /// Returns the cardinality of `self`.
   1051     ///
   1052     /// Note this is constant and is not affected by iteration of
   1053     /// `self`. This isn't the remaining length. [`Self::skip_empty_set`]
   1054     /// contributes towards this value.
   1055     #[expect(
   1056         clippy::arithmetic_side_effects,
   1057         reason = "comment justifies correctness"
   1058     )]
   1059     pub(crate) fn len(&self) -> NonZeroUsizePlus1 {
   1060         // We don't allow construction of `PowerSet` unless the set of features
   1061         // is no more than [`Self::MAX_SET_LEN`]; thus this won't `panic`.
   1062         // Underflow won't occur either since we don't allow construction when the
   1063         // set of features is empty and when we must skip the empty set.
   1064         // `NonZeroUsizePlus1` treats `0` as `usize::MAX + 1`, so we use wrapping addition.
   1065         // This will only wrapp when `self.features.len() == Self::MAX_SET_LEN` and `!self.skip_empty_set`.
   1066         NonZeroUsizePlus1::new(
   1067             (Self::len_minus_one(self.feats.len()) - usize::from(self.skip_empty_set))
   1068                 .wrapping_add(1),
   1069         )
   1070     }
   1071     /// Contructs `Self` based on `features`.
   1072     ///
   1073     /// When iterating the sets, the empty set will be skipped iff `skip_empty_set`;
   1074     /// but this _won't_ contribute to `skipped_sets_counter`.
   1075     ///
   1076     /// Returns `None` iff `features` is empty and `skip_empty_set`.
   1077     fn new(
   1078         features: &'a Features,
   1079         skip_empty_set: bool,
   1080     ) -> Result<Option<Self>, TooManyFeaturesErr> {
   1081         let len = features.0.len();
   1082         match len {
   1083             0 if skip_empty_set => Ok(None),
   1084             ..=Self::MAX_SET_LEN => {
   1085                 let mut buffer = Vec::with_capacity(len);
   1086                 features.0.iter().fold((), |(), key| {
   1087                     buffer.push(key.0.as_ref());
   1088                 });
   1089                 let check_overlap = !pairwise_disconnected(buffer.as_slice(), &features.0);
   1090                 Ok(Some(Self {
   1091                     feats: &features.0,
   1092                     has_remaining: true,
   1093                     check_overlap,
   1094                     // We verified `len <= Self::MAX_SET_LEN`, so this won't `panic`.
   1095                     idx: Self::len_minus_one(len),
   1096                     buffer,
   1097                     // This won't overflow since `usize::MAX = 2^usize::BITS - 1`, `usize::BITS >= 16`, the max
   1098                     // value of `len` is `usize::BITS`.
   1099                     // 16 * usize::BITS < 2^usize::BITS for `usize::BITS > 6`.
   1100                     set: String::with_capacity(len << 4),
   1101                     skipped_sets_counter: 0,
   1102                     skip_empty_set,
   1103                 }))
   1104             }
   1105             _ => Err(TooManyFeaturesErr),
   1106         }
   1107     }
   1108     /// Resets `self` such that iteration returns to the beginning.
   1109     pub(crate) const fn reset(&mut self) {
   1110         // We don't allow construction of `PowerSet` when the number of
   1111         // features exceeds [`Self::MAX_SET_LEN`], so this won't `panic`.
   1112         self.idx = Self::len_minus_one(self.feats.len());
   1113         self.has_remaining = true;
   1114         self.skipped_sets_counter = 0;
   1115     }
   1116     /// Writes the next element into `self.buffer` even if the set contains overlapping features.
   1117     #[expect(
   1118         clippy::arithmetic_side_effects,
   1119         reason = "comment justifies correctness"
   1120     )]
   1121     fn inner_next_set(&mut self) {
   1122         self.buffer.clear();
   1123         self.feats.iter().enumerate().fold((), |(), (i, feat)| {
   1124             if self.idx & (1 << i) != 0 {
   1125                 self.buffer.push(feat.0.as_str());
   1126             }
   1127         });
   1128         if self.idx == 0 {
   1129             self.has_remaining = false;
   1130         // The empty set is always the last set.
   1131         } else if self.idx == 1 && self.skip_empty_set {
   1132             self.idx = 0;
   1133             self.has_remaining = false;
   1134         } else {
   1135             // This won't underflow since `idx > 0`.
   1136             self.idx -= 1;
   1137         }
   1138     }
   1139     /// Transforms the current element into its string form.
   1140     fn current_set(&mut self) {
   1141         self.set.clear();
   1142         self.buffer.iter().fold((), |(), s| {
   1143             self.set.push_str(s);
   1144             self.set.push(',');
   1145         });
   1146         // We remove the trailing comma. In the event `self.set` is empty, this does nothing.
   1147         _ = self.set.pop();
   1148     }
   1149     /// Returns the next set.
   1150     ///
   1151     /// This returns `None` iff there are no more sets to return. It will continue to return `None`
   1152     /// unless [`Self::reset`] is called.
   1153     pub(crate) fn next_set(&mut self) -> Option<&str> {
   1154         self.next_set_with_skip_count().map(|tup| tup.0)
   1155     }
   1156     /// Returns the next set along with the number of set skipped thus far.
   1157     ///
   1158     /// This returns `None` iff there are no more sets to return. It will continue to return `None`
   1159     /// unless [`Self::reset`] is called.
   1160     #[expect(
   1161         clippy::arithmetic_side_effects,
   1162         reason = "comment justifies correctness"
   1163     )]
   1164     pub(crate) fn next_set_with_skip_count(&mut self) -> Option<(&str, usize)> {
   1165         if self.has_remaining {
   1166             if self.check_overlap {
   1167                 while self.has_remaining {
   1168                     self.inner_next_set();
   1169                     if pairwise_disconnected(self.buffer.as_slice(), self.feats) {
   1170                         self.current_set();
   1171                         return Some((&self.set, self.skipped_sets_counter));
   1172                     }
   1173                     // This maxes at `usize::MAX` since we ensure a power set is not created on a
   1174                     // set with more than `usize::BITS` elements.
   1175                     // We set to set every time [`Self::reset`] is called as well.
   1176                     self.skipped_sets_counter += 1;
   1177                 }
   1178                 None
   1179             } else {
   1180                 self.inner_next_set();
   1181                 self.current_set();
   1182                 Some((&self.set, self.skipped_sets_counter))
   1183             }
   1184         } else {
   1185             None
   1186         }
   1187     }
   1188 }
   1189 /// Dependency table.
   1190 enum DepTable {
   1191     /// Library dependencies.
   1192     Dependencies,
   1193     /// Build dependencies.
   1194     BuildDependencies,
   1195 }
   1196 impl DepTable {
   1197     /// Returns the string representation of `self`.
   1198     const fn into_str(self) -> &'static str {
   1199         match self {
   1200             Self::Dependencies => "dependencies",
   1201             Self::BuildDependencies => "build-dependencies",
   1202         }
   1203     }
   1204 }
   1205 /// `"dep:"`.
   1206 const DEP: &[u8; 4] = b"dep:";
   1207 /// Returns `true` iff `utf8` begins with [`DEP`].
   1208 fn is_feature_dependency_a_dependency(utf8: &[u8]) -> bool {
   1209     utf8.starts_with(DEP)
   1210 }
   1211 /// Returns `true` iff `name` does not contain a `'/'` nor begins with [`DEP`].
   1212 fn is_feature_dependency_a_feature(name: &str) -> bool {
   1213     let utf8 = name.as_bytes();
   1214     !(utf8.contains(&b'/') || is_feature_dependency_a_dependency(utf8))
   1215 }
   1216 /// Features in Cargo.toml.
   1217 ///
   1218 /// Note this contains a `Vec` instead of a `HashMap` or `BTreeMap` since we enforce that very few entries exist
   1219 /// due to the exponential nature of generating the power set; thus making a `Vec` more efficient and faster.
   1220 /// This size is so small that we don't even sort and perform a binary search.
   1221 ///
   1222 /// The `String` in the tuple represents the name of the feature, and the `Vec` in the tuple represents the
   1223 /// feature dependencies. The feature dependencies will not contain any dependency that contains a `'/'`
   1224 /// but will contain all others. The name of each feature will not contain a `'/'` nor begin with [`DEP`].
   1225 /// Each dependency that is a feature (i.e., does not begin with [`DEP`]) is well-defined (i.e., is a feature
   1226 /// itself) when `false` is passed to [`Self::extract_from_toml`]; when `true` is passed, then feature dependencies
   1227 /// that are features are not verified to be defined in `self` since implied features still have to be added.
   1228 /// Each feature does not contain any cycles nor redundant dependencies.
   1229 ///
   1230 /// One must still add implied features caused from any optional dependencies iff `true` is passed to
   1231 /// [`Self::extract_from_toml`]; after which, one needs to remove all dependencies that are not features and verify
   1232 /// all dependencies that are features are defined in `self` in order for [`PowerSet`] to work correctly. A feature
   1233 /// with name `<dependency>` needs to be added with an empty `Vec` of dependencies iff no features exist that have a
   1234 /// dependency whose name is `"dep:<dependency>"` _and_ there doesn't already exist a feature with that name.
   1235 /// An error MUST NOT happen if there is such a feature since different kinds of dependencies can have the
   1236 /// same name. While this will allow for the situation where a feature is defined with the same name as
   1237 /// an implied feature, that won't matter once `cargo` is run since it will error anyway.
   1238 #[cfg_attr(test, derive(Debug, PartialEq))]
   1239 pub(crate) struct Features(Vec<(String, Vec<String>)>);
   1240 impl Features {
   1241     /// Returns `true` iff `self` contains a feature named `"default"`.
   1242     pub(crate) fn contains_default(&self) -> bool {
   1243         self.0.iter().any(|f| f.0 == "default")
   1244     }
   1245     /// `panic`s with a static message about the existence of a bug in `validate_dependencies`.
   1246     ///
   1247     /// This is used in lieu of `unreachable` in `validate_dependencies`, `check_redundant_features`
   1248     /// and `extract_feature_dependencies`.
   1249     #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
   1250     fn impossible<T>() -> T {
   1251         unreachable!("there is a bug in manifest::Features::validate_dependencies.")
   1252     }
   1253     /// Verifies dependencies associated with `feature` is valid.
   1254     ///
   1255     /// `dependencies` are assumed to be associated with `feature` which the pair of is checked to be
   1256     /// a key-value pair from `features` iff `allow_implied_features`. This verifies the following:
   1257     ///
   1258     /// * `dependencies` is an array that only contains strings.
   1259     /// * Each string in `dependencies` that does not contain a `'/'` nor begins with [`DEP`] is a key
   1260     ///   in `features` iff `allow_implied_features`.
   1261     /// * `feature` nor any dependency that is a feature in `dependencies` is cyclic.
   1262     ///
   1263     /// `cycle_detection` MUST contain only `feature` when this is called externally.
   1264     ///
   1265     /// This MUST only be called by itself or [`Self::extract_feature_dependencies`].
   1266     fn validate_dependencies<'a>(
   1267         feature: &str,
   1268         dependencies: &'a DeValue<'_>,
   1269         features: &'a Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
   1270         cycle_detection: &mut Vec<&'a str>,
   1271         allow_implied_features: bool,
   1272     ) -> Result<(), FeatureDependenciesErr> {
   1273         if let DeValue::Array(ref info) = *dependencies {
   1274             info.iter().try_fold((), |(), dep_span| {
   1275                 if let DeValue::String(ref dep_name) = *dep_span.get_ref() {
   1276                     if is_feature_dependency_a_feature(dep_name) {
   1277                         if cycle_detection.contains(&dep_name.as_ref()) {
   1278                             Err(FeatureDependenciesErr::CyclicFeature(
   1279                                 dep_name.clone().into_owned(),
   1280                             ))
   1281                         } else if let Some(next_feature) = features.get(dep_name.as_ref()) {
   1282                             cycle_detection.push(dep_name);
   1283                             Self::validate_dependencies(
   1284                                 dep_name,
   1285                                 next_feature.get_ref(),
   1286                                 features,
   1287                                 cycle_detection,
   1288                                 allow_implied_features,
   1289                             )
   1290                             .map(|()| {
   1291                                 // We require calling code to add `feature` before calling this function. We
   1292                                 // always add the most recent feature dependency. Therefore this is not empty.
   1293                                 _ = cycle_detection.pop().unwrap_or_else(Self::impossible);
   1294                             })
   1295                         } else if allow_implied_features {
   1296                             // `dep_name` may be an implied feature which we have yet to add.
   1297                             Ok(())
   1298                         } else {
   1299                             // We require calling code to add `feature` before calling this function. We always
   1300                             // add the most recent feature dependency. Therefore this is not empty.
   1301                             Err(FeatureDependenciesErr::InvalidDependency(
   1302                                 cycle_detection
   1303                                     .pop()
   1304                                     .unwrap_or_else(Self::impossible)
   1305                                     .to_owned(),
   1306                                 dep_name.clone().into_owned(),
   1307                             ))
   1308                         }
   1309                     } else {
   1310                         Ok(())
   1311                     }
   1312                 } else {
   1313                     Err(FeatureDependenciesErr::InvalidDependencyType(
   1314                         feature.to_owned(),
   1315                     ))
   1316                 }
   1317             })
   1318         } else {
   1319             Err(FeatureDependenciesErr::InvalidFeatureType(
   1320                 feature.to_owned(),
   1321             ))
   1322         }
   1323     }
   1324     /// Verifies there are no redundant dependencies that are features in `dependencies`.
   1325     ///
   1326     /// Returns `true` iff there is a redundant dependency.
   1327     ///
   1328     /// This must be called _after_ `validate_dependencies` is called on the same arguments.
   1329     fn check_redundant_dependencies(
   1330         feature: &str,
   1331         dependencies: &DeArray<'_>,
   1332         features: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
   1333         allow_implied_features: bool,
   1334     ) -> bool {
   1335         dependencies.iter().any(|dep_span| {
   1336             if let DeValue::String(ref dep_name) = *dep_span.get_ref() {
   1337                 is_feature_dependency_a_feature(dep_name)
   1338                     && (feature == dep_name
   1339                         || features.get(dep_name.as_ref()).map_or_else(
   1340                             || {
   1341                                 if allow_implied_features {
   1342                                     false
   1343                                 } else {
   1344                                     // We require `validate_dependencies` to be called before this function which
   1345                                     // ensures all features recursively in the `dependencies` are defined as features iff `!allow_implied_features`.
   1346                                     Self::impossible()
   1347                                 }
   1348                             },
   1349                             |next_feature_span| {
   1350                                 Self::check_redundant_dependencies(
   1351                                     feature,
   1352                                     next_feature_span
   1353                                         .get_ref()
   1354                                         .as_array()
   1355                                         // We require `validate_dependencies` to be called before this function
   1356                                         // which ensures all feature dependencies recursively are arrays.
   1357                                         .unwrap_or_else(Self::impossible),
   1358                                     features,
   1359                                     allow_implied_features,
   1360                                 )
   1361                             },
   1362                         ))
   1363             } else {
   1364                 // We require `validate_dependencies` to be called before this function which ensures all
   1365                 // dependencies recursivley in `dependencies` are strings.
   1366                 Self::impossible()
   1367             }
   1368         })
   1369     }
   1370     /// Extracts the feature dependencies associated with `feature`.
   1371     ///
   1372     /// `dependencies` are assumed to be associated with `feature` which the pair of is checked to be
   1373     /// a key-value pair from `features` iff `allow_implied_features`. This verifies the following:
   1374     ///
   1375     /// * `dependencies` is an array that only contains strings.
   1376     /// * Each string in `dependencies` that does not contain a `'/'` nor begins with [`DEP`] is a key
   1377     ///   in `features` iff `allow_implied_features`.
   1378     /// * There is no redundant feature in `dependencies` where "redundant" means the following:
   1379     ///   * There are no cycles (e.g., feature = \["feature"] or feature = \["a"], a = \["b"], b = \["a"]).
   1380     ///   * No unnecessary dependencies that are features (e.g., feature = \["a", "a"] or feature = \["a", "b"]
   1381     ///     a = \["b"], b = \[]).
   1382     /// * There are no duplicate dependencies in `dependencies` that beging with [`DEP`].
   1383     ///
   1384     /// Note since all dependencies that contain a `'/'` are ignored, there may be duplicates of them.
   1385     /// Also when checking for redundant features in `dependencies`, _only_ features are considered; thus
   1386     /// something like the following is allowed: feature = \["dep:a", "a"], a = \["dep:a"].
   1387     ///
   1388     /// This must only be called from [`Self::extract_from_toml`].
   1389     #[expect(
   1390         clippy::arithmetic_side_effects,
   1391         reason = "comment justifies correctness"
   1392     )]
   1393     fn extract_feature_dependencies<'a>(
   1394         feature: &'a str,
   1395         dependencies: &'a DeValue<'_>,
   1396         features: &'a Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
   1397         cycle_buffer: &mut Vec<&'a str>,
   1398         allow_implied_features: bool,
   1399     ) -> Result<Vec<String>, FeatureDependenciesErr> {
   1400         // `Self::validate_dependencies` requires `cycle_buffer` to contain, and only contain, `feature`.
   1401         cycle_buffer.clear();
   1402         cycle_buffer.push(feature);
   1403         Self::validate_dependencies(feature, dependencies, features, cycle_buffer, allow_implied_features).and_then(|()| {
   1404             // `validate_dependencies` ensures `dependencies` is an array.
   1405             let deps = dependencies.as_array().unwrap_or_else(Self::impossible);
   1406             let mut vec_deps = Vec::with_capacity(deps.len());
   1407             deps.iter().enumerate().try_fold((), |(), (idx, dep_span)| if let DeValue::String(ref dep_name) = *dep_span.get_ref() {
   1408                 let dep_utf8 = dep_name.as_bytes();
   1409                 if dep_utf8.contains(&b'/') {
   1410                     Ok(())
   1411                 } else if is_feature_dependency_a_dependency(dep_utf8) {
   1412                     if vec_deps.iter().any(|d| d == dep_name) {
   1413                         Err(FeatureDependenciesErr::RedundantDependency(feature.to_owned(), dep_name.clone().into_owned()))
   1414                     } else {
   1415                         vec_deps.push(dep_name.clone().into_owned());
   1416                         Ok(())
   1417                     }
   1418                 } else if let Some(next_feature_span) = features.get(dep_name.as_ref()) {
   1419                     // `validate_dependencies` ensures all feature
   1420                     // dependencies recursively are arrays.
   1421                     let feat_info = next_feature_span.get_ref().as_array().unwrap_or_else(Self::impossible);
   1422                     // `idx < deps.iter().len()`; thus this won't overflow.
   1423                     deps.iter().skip(idx + 1).try_fold((), |(), next_dep_span| if let DeValue::String(ref next_dep_name) = *next_dep_span.get_ref() {
   1424                         if is_feature_dependency_a_feature(next_dep_name) {
   1425                             if dep_name == next_dep_name {
   1426                                 Err(FeatureDependenciesErr::RedundantDependency(feature.to_owned(), dep_name.clone().into_owned()))
   1427                             } else if Self::check_redundant_dependencies(next_dep_name, feat_info, features, allow_implied_features) {
   1428                                 Err(FeatureDependenciesErr::RedundantDependency(feature.to_owned(), next_dep_name.clone().into_owned()))
   1429                             } else {
   1430                                 features.get(next_dep_name.as_ref()).map_or_else(
   1431                                     || {
   1432                                         if allow_implied_features {
   1433                                             Ok(())
   1434                                         } else {
   1435                                             // `validate_dependencies` ensures all features
   1436                                             // recursively in the feature dependencies are defined
   1437                                             // as features iff `!allow_implied_features`.
   1438                                             Self::impossible()
   1439                                         }
   1440                                     },
   1441                                     |next_dep_feature_span| {
   1442                                         // `validate_dependencies` ensures all feature
   1443                                         // dependencies recursively are arrays.
   1444                                         if Self::check_redundant_dependencies(dep_name, next_dep_feature_span.get_ref().as_array().unwrap_or_else(Self::impossible), features, allow_implied_features) {
   1445                                             Err(FeatureDependenciesErr::RedundantDependency(feature.to_owned(), dep_name.clone().into_owned()))
   1446                                         } else {
   1447                                             Ok(())
   1448                                         }
   1449                                     }
   1450                                 )
   1451                             }
   1452                         } else {
   1453                             Ok(())
   1454                         }
   1455                     } else {
   1456                         // `validate_dependencies` ensures all dependencies recursively in `dependencies` are
   1457                         // strings.
   1458                         Self::impossible()
   1459                     }).map(|()| vec_deps.push(dep_name.clone().into_owned()))
   1460                 } else if allow_implied_features {
   1461                     vec_deps.push(dep_name.clone().into_owned());
   1462                     Ok(())
   1463                 } else {
   1464                     // `validate_dependencies` ensures all features
   1465                     // recursively in `dependencies` are defined as features
   1466                     // iff `!allow_implied_features`.
   1467                     Self::impossible()
   1468                 }
   1469             } else {
   1470                 // `validate_dependencies` ensures all dependencies recursively in `dependencies` are strings.
   1471                 Self::impossible()
   1472             }).map(|()| vec_deps)
   1473         })
   1474     }
   1475     /// Extracts `"features"` from `toml`.
   1476     fn extract_from_toml(
   1477         toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
   1478         allow_implied_features: bool,
   1479     ) -> Result<Self, FeaturesErr> {
   1480         toml.get(FEATURES).map_or_else(
   1481             || Ok(Self(Vec::new())),
   1482             |features_span| {
   1483                 if let DeValue::Table(ref features) = *features_span.get_ref() {
   1484                     let mut cycle_buffer = Vec::with_capacity(features.len());
   1485                     let mut feats = Vec::with_capacity(features.len());
   1486                     features
   1487                         .iter()
   1488                         .try_fold((), |(), (name_span, feature_span)| {
   1489                             let name = name_span.get_ref();
   1490                             if is_feature_dependency_a_feature(name) {
   1491                                 Self::extract_feature_dependencies(
   1492                                     name,
   1493                                     feature_span.get_ref(),
   1494                                     features,
   1495                                     &mut cycle_buffer,
   1496                                     allow_implied_features,
   1497                                 )
   1498                                 .map_err(FeaturesErr::FeatureDependencies)
   1499                                 .map(|deps| {
   1500                                     feats.push((name.clone().into_owned(), deps));
   1501                                 })
   1502                             } else {
   1503                                 Err(FeaturesErr::InvalidName(name.clone().into_owned()))
   1504                             }
   1505                         })
   1506                         .map(|()| Self(feats))
   1507                 } else {
   1508                     Err(FeaturesErr::InvalidType)
   1509                 }
   1510             },
   1511         )
   1512     }
   1513     /// Extracts optional dependencies and adds their corresponding implied feature to `self` iff
   1514     /// `allow_implied_features` and it's appropriate to do so.
   1515     ///
   1516     /// This must only be called from [`Self::add_implied_features`].
   1517     fn add_optional_dependencies(
   1518         &mut self,
   1519         toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
   1520         table: DepTable,
   1521         allow_implied_features: bool,
   1522     ) -> Result<(), DependenciesErr> {
   1523         let table_name = table.into_str();
   1524         toml.get(table_name).map_or(Ok(()), |deps_span| {
   1525             if let DeValue::Table(ref deps) = *deps_span.get_ref() {
   1526                 deps.iter().try_fold((), |(), dep_span| {
   1527                     let dep_name = dep_span.0.get_ref();
   1528                     if is_feature_dependency_a_feature(dep_name) {
   1529                         match *dep_span.1.get_ref() {
   1530                             DeValue::String(_) => Ok(()),
   1531                             DeValue::Table(ref dep_info) => {
   1532                                 dep_info.get(OPTIONAL).map_or(Ok(()), |opt_span| {
   1533                                     if let DeValue::Boolean(ref optional) = *opt_span.get_ref() {
   1534                                         if *optional {
   1535                                             self.0
   1536                                                 .iter()
   1537                                                 .try_fold((), |(), feat| {
   1538                                                     if feat.0 == *dep_name {
   1539                                                         // We already have a feature with the same name,
   1540                                                         // so we don't need to continue.
   1541                                                         Err(())
   1542                                                     } else if feat.1.iter().any(|feat_dep| {
   1543                                                         feat_dep
   1544                                                             .as_bytes()
   1545                                                             .split_at_checked(DEP.len())
   1546                                                             .is_some_and(|(pref, rem)| {
   1547                                                                 pref == DEP
   1548                                                                     && dep_name.as_bytes() == rem
   1549                                                             })
   1550                                                     }) {
   1551                                                         // The feature dependencies contain `"dep:<dep_name>"`,
   1552                                                         // so we don't need to add an implied feature.
   1553                                                         Err(())
   1554                                                     } else {
   1555                                                         // The feature name is not `<dep_name>` and all of
   1556                                                         // feature dependencies of all features are not named
   1557                                                         // `"dep:<dep_name>"`; thus we need to continue our
   1558                                                         // search.
   1559                                                         Ok(())
   1560                                                     }
   1561                                                 })
   1562                                                 .map_or(Ok(()), |()| {
   1563                                                     if allow_implied_features {
   1564                                                         // There is no feature with the name `<dep_name>` nor
   1565                                                         // are there any features that contain a feature
   1566                                                         // dependency named `"dep:<dep_name>"`; thus we must
   1567                                                         // insert an implied feature.
   1568                                                         self.0.push((
   1569                                                             dep_name.clone().into_owned(),
   1570                                                             Vec::new(),
   1571                                                         ));
   1572                                                         Ok(())
   1573                                                     } else {
   1574                                                         Err(DependenciesErr::ImpliedFeature(
   1575                                                             table_name,
   1576                                                             dep_name.clone().into_owned(),
   1577                                                         ))
   1578                                                     }
   1579                                                 })
   1580                                         } else {
   1581                                             Ok(())
   1582                                         }
   1583                                     } else {
   1584                                         Err(DependenciesErr::OptionalType(
   1585                                             table_name,
   1586                                             dep_name.clone().into_owned(),
   1587                                         ))
   1588                                     }
   1589                                 })
   1590                             }
   1591                             DeValue::Integer(_)
   1592                             | DeValue::Float(_)
   1593                             | DeValue::Boolean(_)
   1594                             | DeValue::Datetime(_)
   1595                             | DeValue::Array(_) => Err(DependenciesErr::DependencyType(
   1596                                 table_name,
   1597                                 dep_name.clone().into_owned(),
   1598                             )),
   1599                         }
   1600                     } else {
   1601                         Err(DependenciesErr::Name(
   1602                             table_name,
   1603                             dep_name.clone().into_owned(),
   1604                         ))
   1605                     }
   1606                 })
   1607             } else {
   1608                 Err(DependenciesErr::Type(table_name))
   1609             }
   1610         })
   1611     }
   1612     /// Adds implied features to `self` based on the optional dependencies in `toml` iff `allow_implied_features`.
   1613     fn add_implied_features(
   1614         &mut self,
   1615         toml: &Map<Spanned<Cow<'_, str>>, Spanned<DeValue<'_>>>,
   1616         allow_implied_features: bool,
   1617     ) -> Result<(), ImpliedFeaturesErr> {
   1618         self.add_optional_dependencies(toml, DepTable::Dependencies, allow_implied_features).map_err(ImpliedFeaturesErr::Dependencies).and_then(|()| self.add_optional_dependencies(toml, DepTable::BuildDependencies, allow_implied_features).map_err(ImpliedFeaturesErr::Dependencies).and_then(|()| toml.get(TARGET).map_or_else(
   1619             || Ok(()),
   1620             |target_span| {
   1621                 if let DeValue::Table(ref target) = *target_span.get_ref() {
   1622                     target.iter().try_fold((), |(), target_platform_span| {
   1623                         if let DeValue::Table(ref target_platform) = *target_platform_span.1.get_ref() {
   1624                             self.add_optional_dependencies(target_platform, DepTable::Dependencies, allow_implied_features).map_err(|e| ImpliedFeaturesErr::TagetPlatformDependencies(target_platform_span.0.get_ref().clone().into_owned(), e)).and_then(|()| self.add_optional_dependencies(target_platform, DepTable::BuildDependencies, allow_implied_features).map_err(|e| ImpliedFeaturesErr::TagetPlatformDependencies(target_platform_span.0.get_ref().clone().into_owned(), e)))
   1625                         } else {
   1626                             Err(ImpliedFeaturesErr::TargetPlatformType(target_platform_span.0.get_ref().clone().into_owned()))
   1627                         }
   1628                     })
   1629                 } else {
   1630                     Err(ImpliedFeaturesErr::TargetType)
   1631                 }
   1632             }
   1633         ).and_then(|()| {
   1634             if allow_implied_features {
   1635                 // We don't have to worry about cyclic features or anything other than the lack of a feature with
   1636                 // the name of the feature dependency.
   1637                 self.0.iter().try_fold((), |(), feature| feature.1.iter().try_fold((), |(), dep| {
   1638                      // We didn't save any feature dependencies that contain `'/'`, so we simply have to check if
   1639                      // a dependency begins with [`DEP`] to skip it.
   1640                      if is_feature_dependency_a_dependency(dep.as_bytes()) || self.0.iter().any(|other_feature| other_feature.0 == *dep) {
   1641                          Ok(())
   1642                      } else {
   1643                          Err(ImpliedFeaturesErr::InvalidDependency(feature.0.clone(), dep.clone()))
   1644                      }
   1645                  }))
   1646             } else {
   1647                 // When `!allowed_implied_features`, [`Self::validate_dependencies`] verifies non-dependency
   1648                 // feature dependencies are defined as features.
   1649                 Ok(())
   1650             }
   1651         })))
   1652     }
   1653     /// Returns the power set of `self` with semantically equivalent sets removed.
   1654     ///
   1655     /// The empty set of features is skipped iff `skip_no_feats`. None is only
   1656     /// returned if there are no sets of features. This is only possible iff
   1657     /// `self` contains no features and `skip_no_feats`.
   1658     pub(crate) fn power_set(
   1659         &self,
   1660         skip_no_feats: bool,
   1661     ) -> Result<Option<PowerSet<'_>>, TooManyFeaturesErr> {
   1662         PowerSet::new(self, skip_no_feats)
   1663     }
   1664 }
   1665 /// Package and features in `Cargo.toml`.
   1666 #[cfg_attr(test, derive(Debug, PartialEq))]
   1667 pub(crate) struct Manifest {
   1668     /// The package.
   1669     package: Package,
   1670     /// The features.
   1671     features: Features,
   1672 }
   1673 impl Manifest {
   1674     /// Returns the defined MSRV iff there was one defined.
   1675     pub(crate) const fn package(&self) -> &Package {
   1676         &self.package
   1677     }
   1678     /// Returns the defined features.
   1679     ///
   1680     /// Note the returned `Features` doesn't have any cyclic features, each feature dependency for a given
   1681     /// feature is a feature itself, and there are no redundant feature dependencies for a given feature.
   1682     pub(crate) const fn features(&self) -> &Features {
   1683         &self.features
   1684     }
   1685     /// Returns the data needed from `Cargo.toml`.
   1686     ///
   1687     /// Note `ignore_features` MUST not contain an empty `String`.
   1688     #[expect(
   1689         clippy::arithmetic_side_effects,
   1690         reason = "comments justify correctness"
   1691     )]
   1692     #[expect(
   1693         clippy::needless_pass_by_value,
   1694         reason = "want to drop `val` as soon as possible"
   1695     )]
   1696     pub(crate) fn from_toml(
   1697         val: String,
   1698         allow_implied_features: bool,
   1699         cargo_toml: &Path,
   1700         ignore_features: &[String],
   1701     ) -> Result<Self, Box<ManifestErr>> {
   1702         Map::parse(val.as_str())
   1703             .map_err(|e| Box::new(ManifestErr::Toml(e, cargo_toml.to_path_buf())))
   1704             .and_then(|span| {
   1705                 let cargo = span.get_ref();
   1706                 Package::extract_from_toml(cargo, cargo_toml)
   1707                     .map_err(|e| Box::new(ManifestErr::Package(e, cargo_toml.to_path_buf())))
   1708                     .and_then(|package| {
   1709                         Features::extract_from_toml(cargo, allow_implied_features)
   1710                             .map_err(|e| {
   1711                                 Box::new(ManifestErr::Features(e, cargo_toml.to_path_buf()))
   1712                             })
   1713                             .and_then(|mut features| {
   1714                                 features
   1715                                     .add_implied_features(cargo, allow_implied_features)
   1716                                     .map_err(|e| {
   1717                                         Box::new(ManifestErr::ImpliedFeatures(
   1718                                             e,
   1719                                             cargo_toml.to_path_buf(),
   1720                                         ))
   1721                                     })
   1722                                     .and_then(|()| {
   1723                                         features.0.iter_mut().fold(
   1724                                             (),
   1725                                             |(), &mut (_, ref mut deps)| {
   1726                                                 deps.retain(|d| {
   1727                                                     // We retain only features. Since we didn't save any
   1728                                                     // dependencies that contain `'/'`, it's slightly faster to just
   1729                                                     // check that a feature dependency is not a dependency.
   1730                                                     !is_feature_dependency_a_dependency(
   1731                                                         d.as_bytes(),
   1732                                                     )
   1733                                                 });
   1734                                             },
   1735                                         );
   1736                                         // First we ensure all features we are to ignore are defined;
   1737                                         // while doing this, we remove the feature. Note `ignore_features`
   1738                                         // and `features` only contain distinct features, so we simply
   1739                                         // have to check for the first occurrence.
   1740                                         // Note calling code is required to have removed the empty
   1741                                         // string if it had existed.
   1742                                         ignore_features
   1743                                             .iter()
   1744                                             .try_fold((), |(), ig_feat| {
   1745                                                 features
   1746                                                     .0
   1747                                                     .iter()
   1748                                                     .try_fold(0, |idx, info| {
   1749                                                         if info.0 == *ig_feat {
   1750                                                             Err(idx)
   1751                                                         } else {
   1752                                                             // Clearly free from overflow.
   1753                                                             Ok(idx + 1)
   1754                                                         }
   1755                                                     })
   1756                                                     .map_or_else(
   1757                                                         |idx| {
   1758                                                             drop(features.0.swap_remove(idx));
   1759                                                             Ok(())
   1760                                                         },
   1761                                                         |_| {
   1762                                                             Err(Box::new(
   1763                                                                 ManifestErr::UndefinedIgnoreFeature(
   1764                                                                     ig_feat.clone(),
   1765                                                                     cargo_toml.to_path_buf(),
   1766                                                                 ),
   1767                                                             ))
   1768                                                         },
   1769                                                     )
   1770                                             })
   1771                                             .map(|()| {
   1772                                                 // Now we remove all features that depend on the
   1773                                                 // features we are to ignore.
   1774                                                 ignore_features.iter().fold((), |(), ig_feat| {
   1775                                                     features.0.retain(|info| {
   1776                                                         !info.1.iter().any(|d| d == ig_feat)
   1777                                                     });
   1778                                                 });
   1779                                                 Self { package, features }
   1780                                             })
   1781                                     })
   1782                             })
   1783                     })
   1784             })
   1785     }
   1786 }
   1787 #[cfg(test)]
   1788 mod tests {
   1789     use super::{
   1790         DependenciesErr, FeatureDependenciesErr, Features, FeaturesErr, ImpliedFeaturesErr,
   1791         Manifest, ManifestErr, Msrv, NonZeroUsizePlus1, Package, PackageErr, Path, PathBuf,
   1792         PowerSet, TooManyFeaturesErr, TryLockError, WorkspaceErr,
   1793     };
   1794     impl PartialEq for PackageErr {
   1795         #[expect(clippy::cognitive_complexity, reason = "long match expression")]
   1796         fn eq(&self, other: &Self) -> bool {
   1797             match *self {
   1798                 Self::Missing => matches!(*other, Self::Missing),
   1799                 Self::InvalidType => matches!(*other, Self::InvalidType),
   1800                 Self::MissingName => matches!(*other, Self::MissingName),
   1801                 Self::InvalidNameType => matches!(*other, Self::InvalidNameType),
   1802                 Self::InvalidMsrvType => matches!(*other, Self::InvalidMsrvType),
   1803                 Self::Msrv => matches!(*other, Self::Msrv),
   1804                 Self::MsrvWorkspaceMissing => matches!(*other, Self::MsrvWorkspaceMissing),
   1805                 Self::MsrvWorkspaceVal => matches!(*other, Self::MsrvWorkspaceVal),
   1806                 Self::InvalidWorkspaceType => matches!(*other, Self::InvalidWorkspaceType),
   1807                 Self::WorkspaceIo(ref e) => {
   1808                     matches!(*other, Self::WorkspaceIo(ref e2) if e.kind() == e2.kind())
   1809                 }
   1810                 Self::WorkspaceLock(ref e) => {
   1811                     matches!(*other, Self::WorkspaceLock(ref e2) if match *e {
   1812                         TryLockError::Error(ref inner_e) => matches!(*e2, TryLockError::Error(ref inner_e2) if inner_e.kind() == inner_e2.kind()),
   1813                         TryLockError::WouldBlock => matches!(*e2, TryLockError::WouldBlock),
   1814                     })
   1815                 }
   1816                 Self::WorkspaceLenMismatch => matches!(*other, Self::WorkspaceLenMismatch),
   1817                 Self::WorkspaceDoesNotExist => matches!(*other, Self::WorkspaceDoesNotExist),
   1818                 Self::WorkspaceRead(ref e, ref p) => {
   1819                     matches!(*other, Self::WorkspaceRead(ref e2, ref p2) if e.kind() == e2.kind() && p == p2)
   1820                 }
   1821                 Self::WorkspaceReadLock(ref e, ref p) => {
   1822                     matches!(*other, Self::WorkspaceReadLock(ref e2, ref p2) if p == p2 && match *e {
   1823                         TryLockError::Error(ref inner_e) => matches!(*e2, TryLockError::Error(ref inner_e2) if inner_e.kind() == inner_e2.kind()),
   1824                         TryLockError::WouldBlock => matches!(*e2, TryLockError::WouldBlock),
   1825                     })
   1826                 }
   1827                 Self::WorkspaceReadLenMismatch(ref p) => {
   1828                     matches!(*other, Self::WorkspaceReadLenMismatch(ref p2) if p == p2)
   1829                 }
   1830                 Self::WorkspaceToml(ref e, ref p) => {
   1831                     matches!(*other, Self::WorkspaceToml(ref e2, ref p2) if e == e2 && p == p2)
   1832                 }
   1833                 Self::Workspace(e, ref p) => {
   1834                     matches!(*other, Self::Workspace(e2, ref p2) if e == e2 && p == p2)
   1835                 }
   1836             }
   1837         }
   1838     }
   1839     #[expect(
   1840         clippy::cognitive_complexity,
   1841         clippy::too_many_lines,
   1842         reason = "want to test a lot of things"
   1843     )]
   1844     #[test]
   1845     fn cargo_toml() {
   1846         assert!(
   1847             Manifest::from_toml("a".to_owned(), false, Path::new(""), &[])
   1848                 .map_or_else(|e| matches!(*e, ManifestErr::Toml(_, _)), |_| false)
   1849         );
   1850         assert_eq!(
   1851             Manifest::from_toml(String::new(), false, Path::new(""), &[]),
   1852             Err(Box::new(ManifestErr::Package(
   1853                 PackageErr::Missing,
   1854                 PathBuf::new()
   1855             )))
   1856         );
   1857         assert_eq!(
   1858             Manifest::from_toml("[' package']".to_owned(), false, Path::new(""), &[]),
   1859             Err(Box::new(ManifestErr::Package(
   1860                 PackageErr::Missing,
   1861                 PathBuf::new()
   1862             )))
   1863         );
   1864         assert_eq!(
   1865             Manifest::from_toml("['package ']".to_owned(), false, Path::new(""), &[]),
   1866             Err(Box::new(ManifestErr::Package(
   1867                 PackageErr::Missing,
   1868                 PathBuf::new()
   1869             )))
   1870         );
   1871         assert_eq!(
   1872             Manifest::from_toml("package=2".to_owned(), false, Path::new(""), &[]),
   1873             Err(Box::new(ManifestErr::Package(
   1874                 PackageErr::InvalidType,
   1875                 PathBuf::new()
   1876             )))
   1877         );
   1878         assert_eq!(
   1879             Manifest::from_toml("[package]".to_owned(), false, Path::new(""), &[]),
   1880             Err(Box::new(ManifestErr::Package(
   1881                 PackageErr::MissingName,
   1882                 PathBuf::new()
   1883             )))
   1884         );
   1885         assert_eq!(
   1886             Manifest::from_toml("[package]\nname=true".to_owned(), false, Path::new(""), &[]),
   1887             Err(Box::new(ManifestErr::Package(
   1888                 PackageErr::InvalidNameType,
   1889                 PathBuf::new()
   1890             )))
   1891         );
   1892         assert_eq!(
   1893             Manifest::from_toml(
   1894                 "[package]\nname=\"\"\n\nrust-version=2".to_owned(),
   1895                 false,
   1896                 Path::new(""),
   1897                 &[]
   1898             ),
   1899             Err(Box::new(ManifestErr::Package(
   1900                 PackageErr::InvalidMsrvType,
   1901                 PathBuf::new()
   1902             )))
   1903         );
   1904         assert_eq!(
   1905             Manifest::from_toml(
   1906                 "[package]\nname=\"\"\nrust-version=\"\"".to_owned(),
   1907                 false,
   1908                 Path::new(""),
   1909                 &[]
   1910             ),
   1911             Err(Box::new(ManifestErr::Package(
   1912                 PackageErr::Msrv,
   1913                 PathBuf::new()
   1914             )))
   1915         );
   1916         assert_eq!(
   1917             Manifest::from_toml(
   1918                 "[package]\nname=\"\"\nrust-version=\"a\"".to_owned(),
   1919                 false,
   1920                 Path::new(""),
   1921                 &[]
   1922             ),
   1923             Err(Box::new(ManifestErr::Package(
   1924                 PackageErr::Msrv,
   1925                 PathBuf::new()
   1926             )))
   1927         );
   1928         assert_eq!(
   1929             Manifest::from_toml(
   1930                 "[package]\nname=\"\"\nrust-version=\"1.00.0\"".to_owned(),
   1931                 false,
   1932                 Path::new(""),
   1933                 &[]
   1934             ),
   1935             Err(Box::new(ManifestErr::Package(
   1936                 PackageErr::Msrv,
   1937                 PathBuf::new()
   1938             )))
   1939         );
   1940         assert_eq!(
   1941             Manifest::from_toml(
   1942                 "[package]\nname=\"\"\nrust-version=\"1..0\"".to_owned(),
   1943                 false,
   1944                 Path::new(""),
   1945                 &[]
   1946             ),
   1947             Err(Box::new(ManifestErr::Package(
   1948                 PackageErr::Msrv,
   1949                 PathBuf::new()
   1950             )))
   1951         );
   1952         assert_eq!(
   1953             Manifest::from_toml(
   1954                 "[package]\nname=\"\"\nrust-version=\"1.\"".to_owned(),
   1955                 false,
   1956                 Path::new(""),
   1957                 &[]
   1958             ),
   1959             Err(Box::new(ManifestErr::Package(
   1960                 PackageErr::Msrv,
   1961                 PathBuf::new()
   1962             )))
   1963         );
   1964         assert_eq!(
   1965             Manifest::from_toml(
   1966                 "[package]\nname=\"\"\nrust-version=\"01.0.0\"".to_owned(),
   1967                 false,
   1968                 Path::new(""),
   1969                 &[]
   1970             ),
   1971             Err(Box::new(ManifestErr::Package(
   1972                 PackageErr::Msrv,
   1973                 PathBuf::new()
   1974             )))
   1975         );
   1976         assert_eq!(
   1977             Manifest::from_toml(
   1978                 "[package]\nname=\"\"\nrust-version=\"1.0.0.1\"".to_owned(),
   1979                 false,
   1980                 Path::new(""),
   1981                 &[]
   1982             ),
   1983             Err(Box::new(ManifestErr::Package(
   1984                 PackageErr::Msrv,
   1985                 PathBuf::new()
   1986             )))
   1987         );
   1988         assert_eq!(
   1989             Manifest::from_toml(
   1990                 "[package]\nname=\"\"\nrust-version=\"111111111111111111111111.2.3\"".to_owned(),
   1991                 false,
   1992                 Path::new(""),
   1993                 &[]
   1994             ),
   1995             Err(Box::new(ManifestErr::Package(
   1996                 PackageErr::Msrv,
   1997                 PathBuf::new()
   1998             )))
   1999         );
   2000         assert_eq!(
   2001             Manifest::from_toml(
   2002                 "[package]\nname=\"\"\nrust-version=\"1.0.0-nightly\"".to_owned(),
   2003                 false,
   2004                 Path::new(""),
   2005                 &[]
   2006             ),
   2007             Err(Box::new(ManifestErr::Package(
   2008                 PackageErr::Msrv,
   2009                 PathBuf::new()
   2010             )))
   2011         );
   2012         assert_eq!(
   2013             Manifest::from_toml(
   2014                 "[package]\nname=\"\"\nrust-version=\"-1.0.0\"".to_owned(),
   2015                 false,
   2016                 Path::new(""),
   2017                 &[]
   2018             ),
   2019             Err(Box::new(ManifestErr::Package(
   2020                 PackageErr::Msrv,
   2021                 PathBuf::new()
   2022             )))
   2023         );
   2024         assert_eq!(
   2025             Manifest::from_toml(
   2026                 "[package]\nname=\"\"\nrust-version=\" 1.0.0\"".to_owned(),
   2027                 false,
   2028                 Path::new(""),
   2029                 &[]
   2030             ),
   2031             Err(Box::new(ManifestErr::Package(
   2032                 PackageErr::Msrv,
   2033                 PathBuf::new()
   2034             )))
   2035         );
   2036         assert_eq!(
   2037             Manifest::from_toml(
   2038                 "[package]\nname=\"\"\nrust-version=\"1.0.0 \"".to_owned(),
   2039                 false,
   2040                 Path::new(""),
   2041                 &[]
   2042             ),
   2043             Err(Box::new(ManifestErr::Package(
   2044                 PackageErr::Msrv,
   2045                 PathBuf::new()
   2046             )))
   2047         );
   2048         assert_eq!(
   2049             Manifest::from_toml(
   2050                 "[package]\nname=\"\"\nrust-version={}".to_owned(),
   2051                 false,
   2052                 Path::new(""),
   2053                 &[]
   2054             ),
   2055             Err(Box::new(ManifestErr::Package(
   2056                 PackageErr::MsrvWorkspaceMissing,
   2057                 PathBuf::new()
   2058             )))
   2059         );
   2060         assert_eq!(
   2061             Manifest::from_toml(
   2062                 "[package]\nname=\"\"\nrust-version={workspace=2}".to_owned(),
   2063                 false,
   2064                 Path::new(""),
   2065                 &[]
   2066             ),
   2067             Err(Box::new(ManifestErr::Package(
   2068                 PackageErr::MsrvWorkspaceVal,
   2069                 PathBuf::new()
   2070             )))
   2071         );
   2072         assert_eq!(
   2073             Manifest::from_toml(
   2074                 "[package]\nname=\"\"\nrust-version={workspace=false}".to_owned(),
   2075                 false,
   2076                 Path::new(""),
   2077                 &[]
   2078             ),
   2079             Err(Box::new(ManifestErr::Package(
   2080                 PackageErr::MsrvWorkspaceVal,
   2081                 PathBuf::new()
   2082             )))
   2083         );
   2084         assert_eq!(
   2085             Manifest::from_toml(
   2086                 "[package]\nname=\"\"\nrust-version={workspace=true}\nworkspace=2".to_owned(),
   2087                 false,
   2088                 Path::new(""),
   2089                 &[]
   2090             ),
   2091             Err(Box::new(ManifestErr::Package(
   2092                 PackageErr::InvalidWorkspaceType,
   2093                 PathBuf::new()
   2094             )))
   2095         );
   2096         assert_eq!(
   2097             Manifest::from_toml(
   2098                 "workspace=2\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
   2099                 false,
   2100                 Path::new(""),
   2101                 &[]
   2102             ),
   2103             Err(Box::new(ManifestErr::Package(
   2104                 PackageErr::Workspace(WorkspaceErr::InvalidType, PathBuf::new()),
   2105                 PathBuf::new()
   2106             )))
   2107         );
   2108         assert_eq!(
   2109             Manifest::from_toml(
   2110                 "[workspace]\n[package]\nname=\"\"\nrust-version={workspace=true}".to_owned(),
   2111                 false,
   2112                 Path::new(""),
   2113                 &[]
   2114             ),
   2115             Err(Box::new(ManifestErr::Package(
   2116                 PackageErr::Workspace(WorkspaceErr::MissingPackage, PathBuf::new()),
   2117                 PathBuf::new()
   2118             )))
   2119         );
   2120         assert_eq!(
   2121             Manifest::from_toml(
   2122                 "[workspace]\npackage=2\n[package]\nname=\"\"\nrust-version={workspace=true}"
   2123                     .to_owned(),
   2124                 false,
   2125                 Path::new(""),
   2126                 &[]
   2127             ),
   2128             Err(Box::new(ManifestErr::Package(
   2129                 PackageErr::Workspace(WorkspaceErr::InvalidPackageType, PathBuf::new()),
   2130                 PathBuf::new()
   2131             )))
   2132         );
   2133         assert_eq!(
   2134             Manifest::from_toml(
   2135                 "[workspace.package]\n[package]\nname=\"\"\nrust-version={workspace=true}"
   2136                     .to_owned(),
   2137                 false,
   2138                 Path::new(""),
   2139                 &[]
   2140             ),
   2141             Err(Box::new(ManifestErr::Package(
   2142                 PackageErr::Workspace(WorkspaceErr::MissingPackageMsrv, PathBuf::new()),
   2143                 PathBuf::new()
   2144             )))
   2145         );
   2146         assert_eq!(
   2147             Manifest::from_toml(
   2148                 "[workspace.package]\nrust-version={}\n[package]\nname=\"\"\nrust-version={workspace=true}"
   2149                     .to_owned(),
   2150                 false,
   2151                 Path::new(""),
   2152                 &[]
   2153             ),
   2154             Err(Box::new(ManifestErr::Package(
   2155                 PackageErr::Workspace(WorkspaceErr::InvalidPackageMsrvType, PathBuf::new()),
   2156                 PathBuf::new()
   2157             )))
   2158         );
   2159         assert_eq!(
   2160             Manifest::from_toml(
   2161                 "[workspace.package]\nrust-version=\"\"\n[package]\nname=\"\"\nrust-version={workspace=true}"
   2162                     .to_owned(),
   2163                 false,
   2164                 Path::new(""),
   2165                 &[]
   2166             ),
   2167             Err(Box::new(ManifestErr::Package(
   2168                 PackageErr::Workspace(WorkspaceErr::Msrv, PathBuf::new()),
   2169                 PathBuf::new()
   2170             )))
   2171         );
   2172         assert_eq!(
   2173             Manifest::from_toml(
   2174                 "features=2\n[package]\nname=\"\"".to_owned(),
   2175                 false,
   2176                 Path::new(""),
   2177                 &[]
   2178             ),
   2179             Err(Box::new(ManifestErr::Features(
   2180                 FeaturesErr::InvalidType,
   2181                 PathBuf::new()
   2182             )))
   2183         );
   2184         assert_eq!(
   2185             Manifest::from_toml(
   2186                 "[features]\n\"/\"=[]\n[package]\nname=\"\"".to_owned(),
   2187                 false,
   2188                 Path::new(""),
   2189                 &[]
   2190             ),
   2191             Err(Box::new(ManifestErr::Features(
   2192                 FeaturesErr::InvalidName("/".to_owned()),
   2193                 PathBuf::new()
   2194             )))
   2195         );
   2196         assert_eq!(
   2197             Manifest::from_toml(
   2198                 "[features]\n\"dep:\"=[]\n[package]\nname=\"\"".to_owned(),
   2199                 false,
   2200                 Path::new(""),
   2201                 &[]
   2202             ),
   2203             Err(Box::new(ManifestErr::Features(
   2204                 FeaturesErr::InvalidName("dep:".to_owned()),
   2205                 PathBuf::new()
   2206             )))
   2207         );
   2208         assert_eq!(
   2209             Manifest::from_toml(
   2210                 "[features]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
   2211                 false,
   2212                 Path::new(""),
   2213                 &[]
   2214             ),
   2215             Err(Box::new(ManifestErr::Features(
   2216                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidFeatureType(
   2217                     String::new()
   2218                 )),
   2219                 PathBuf::new()
   2220             )))
   2221         );
   2222         assert_eq!(
   2223             Manifest::from_toml(
   2224                 "[features]\n\"\"=[true]\n[package]\nname=\"\"".to_owned(),
   2225                 false,
   2226                 Path::new(""),
   2227                 &[]
   2228             ),
   2229             Err(Box::new(ManifestErr::Features(
   2230                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependencyType(
   2231                     String::new()
   2232                 )),
   2233                 PathBuf::new()
   2234             )))
   2235         );
   2236         assert_eq!(
   2237             Manifest::from_toml(
   2238                 "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
   2239                 false,
   2240                 Path::new(""),
   2241                 &[]
   2242             ),
   2243             Err(Box::new(ManifestErr::Features(
   2244                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependency(
   2245                     String::new(),
   2246                     "foo".to_owned()
   2247                 )),
   2248                 PathBuf::new()
   2249             )))
   2250         );
   2251         // Feature dependencies can't be implied features when implied features are forbidden.
   2252         assert_eq!(
   2253             Manifest::from_toml(
   2254                 "[dependencies]\nfoo={optional=true}\n[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\""
   2255                     .to_owned(),
   2256                 false,
   2257                 Path::new(""),
   2258                 &[]
   2259             ),
   2260             Err(Box::new(ManifestErr::Features(
   2261                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependency(
   2262                     String::new(),
   2263                     "foo".to_owned()
   2264                 )),
   2265                 PathBuf::new()
   2266             )))
   2267         );
   2268         assert_eq!(
   2269             Manifest::from_toml(
   2270                 "[features]\n\"\"=[\"\"]\n[package]\nname=\"\"".to_owned(),
   2271                 false,
   2272                 Path::new(""),
   2273                 &[]
   2274             ),
   2275             Err(Box::new(ManifestErr::Features(
   2276                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(
   2277                     String::new()
   2278                 )),
   2279                 PathBuf::new()
   2280             )))
   2281         );
   2282         assert_eq!(
   2283             Manifest::from_toml(
   2284                 "[features]\n\"\"=[\"a\"]\na=[\"\"]\n[package]\nname=\"\"".to_owned(),
   2285                 false,
   2286                 Path::new(""),
   2287                 &[]
   2288             ),
   2289             Err(Box::new(ManifestErr::Features(
   2290                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(
   2291                     String::new()
   2292                 )),
   2293                 PathBuf::new()
   2294             )))
   2295         );
   2296         assert_eq!(
   2297             Manifest::from_toml(
   2298                 "[features]\n\"\"=[\"a\"]\na=[\"b\"]\nb=[\"a\"]\n[package]\nname=\"\"".to_owned(),
   2299                 false,
   2300                 Path::new(""),
   2301                 &[]
   2302             ),
   2303             Err(Box::new(ManifestErr::Features(
   2304                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(
   2305                     "a".to_owned()
   2306                 )),
   2307                 PathBuf::new()
   2308             )))
   2309         );
   2310         assert_eq!(
   2311             Manifest::from_toml(
   2312                 "[features]\n\"\"=[\"a\"]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]\nname=\"\""
   2313                     .to_owned(),
   2314                 false,
   2315                 Path::new(""),
   2316                 &[]
   2317             ),
   2318             Err(Box::new(ManifestErr::Features(
   2319                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(
   2320                     "a".to_owned()
   2321                 )),
   2322                 PathBuf::new()
   2323             )))
   2324         );
   2325         assert_eq!(
   2326             Manifest::from_toml(
   2327                 "[features]\n\"\"=[]\na=[\"c\",\"b\"]\nb=[\"a\"]\nc=[]\n[package]\nname=\"\""
   2328                     .to_owned(),
   2329                 false,
   2330                 Path::new(""),
   2331                 &[]
   2332             ),
   2333             Err(Box::new(ManifestErr::Features(
   2334                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::CyclicFeature(
   2335                     "a".to_owned()
   2336                 )),
   2337                 PathBuf::new()
   2338             )))
   2339         );
   2340         assert_eq!(
   2341             Manifest::from_toml(
   2342                 "[features]\n\"\"=[\"a\",\"b\"]\na=[\"b\"]\nb=[]\n[package]\nname=\"\"".to_owned(),
   2343                 false,
   2344                 Path::new(""),
   2345                 &[]
   2346             ),
   2347             Err(Box::new(ManifestErr::Features(
   2348                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::RedundantDependency(
   2349                     String::new(),
   2350                     "b".to_owned()
   2351                 )),
   2352                 PathBuf::new()
   2353             )))
   2354         );
   2355         assert_eq!(
   2356             Manifest::from_toml(
   2357                 "[features]\n\"\"=[\"a\",\"a\"]\na=[]\n[package]\nname=\"\"".to_owned(),
   2358                 false,
   2359                 Path::new(""),
   2360                 &[]
   2361             ),
   2362             Err(Box::new(ManifestErr::Features(
   2363                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::RedundantDependency(
   2364                     String::new(),
   2365                     "a".to_owned()
   2366                 )),
   2367                 PathBuf::new()
   2368             )))
   2369         );
   2370         // Duplicate `"dep:"` feature dependencies error.
   2371         assert_eq!(
   2372             Manifest::from_toml(
   2373                 "[features]\n\"\"=[\"dep:\",\"dep:\"]\na=[]\n[package]\nname=\"\"".to_owned(),
   2374                 false,
   2375                 Path::new(""),
   2376                 &[]
   2377             ),
   2378             Err(Box::new(ManifestErr::Features(
   2379                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::RedundantDependency(
   2380                     String::new(),
   2381                     "dep:".to_owned()
   2382                 )),
   2383                 PathBuf::new()
   2384             )))
   2385         );
   2386         assert_eq!(
   2387             Manifest::from_toml(
   2388                 "target=2\n[package]\nname=\"\"".to_owned(),
   2389                 false,
   2390                 Path::new(""),
   2391                 &[]
   2392             ),
   2393             Err(Box::new(ManifestErr::ImpliedFeatures(
   2394                 ImpliedFeaturesErr::TargetType,
   2395                 PathBuf::new()
   2396             )))
   2397         );
   2398         assert_eq!(
   2399             Manifest::from_toml(
   2400                 "dependencies=2\n[package]\nname=\"\"".to_owned(),
   2401                 false,
   2402                 Path::new(""),
   2403                 &[]
   2404             ),
   2405             Err(Box::new(ManifestErr::ImpliedFeatures(
   2406                 ImpliedFeaturesErr::Dependencies(DependenciesErr::Type("dependencies")),
   2407                 PathBuf::new()
   2408             )))
   2409         );
   2410         assert_eq!(
   2411             Manifest::from_toml(
   2412                 "build-dependencies=2\n[package]\nname=\"\"".to_owned(),
   2413                 false,
   2414                 Path::new(""),
   2415                 &[]
   2416             ),
   2417             Err(Box::new(ManifestErr::ImpliedFeatures(
   2418                 ImpliedFeaturesErr::Dependencies(DependenciesErr::Type("build-dependencies")),
   2419                 PathBuf::new(),
   2420             )))
   2421         );
   2422         assert_eq!(
   2423             Manifest::from_toml(
   2424                 "[dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2425                 false,
   2426                 Path::new(""),
   2427                 &[]
   2428             ),
   2429             Err(Box::new(ManifestErr::ImpliedFeatures(
   2430                 ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
   2431                     "dependencies",
   2432                     "dep:".to_owned()
   2433                 )),
   2434                 PathBuf::new(),
   2435             )))
   2436         );
   2437         assert_eq!(
   2438             Manifest::from_toml(
   2439                 "[dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2440                 false,
   2441                 Path::new(""),
   2442                 &[]
   2443             ),
   2444             Err(Box::new(ManifestErr::ImpliedFeatures(
   2445                 ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
   2446                     "dependencies",
   2447                     "/".to_owned()
   2448                 )),
   2449                 PathBuf::new(),
   2450             )))
   2451         );
   2452         assert_eq!(
   2453             Manifest::from_toml(
   2454                 "[build-dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2455                 false,
   2456                 Path::new(""),
   2457                 &[]
   2458             ),
   2459             Err(Box::new(ManifestErr::ImpliedFeatures(
   2460                 ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
   2461                     "build-dependencies",
   2462                     "dep:".to_owned()
   2463                 )),
   2464                 PathBuf::new(),
   2465             )))
   2466         );
   2467         assert_eq!(
   2468             Manifest::from_toml(
   2469                 "[build-dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2470                 false,
   2471                 Path::new(""),
   2472                 &[]
   2473             ),
   2474             Err(Box::new(ManifestErr::ImpliedFeatures(
   2475                 ImpliedFeaturesErr::Dependencies(DependenciesErr::Name(
   2476                     "build-dependencies",
   2477                     "/".to_owned()
   2478                 )),
   2479                 PathBuf::new(),
   2480             )))
   2481         );
   2482         assert_eq!(
   2483             Manifest::from_toml(
   2484                 "[dependencies]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
   2485                 false,
   2486                 Path::new(""),
   2487                 &[]
   2488             ),
   2489             Err(Box::new(ManifestErr::ImpliedFeatures(
   2490                 ImpliedFeaturesErr::Dependencies(DependenciesErr::DependencyType(
   2491                     "dependencies",
   2492                     String::new()
   2493                 )),
   2494                 PathBuf::new(),
   2495             )))
   2496         );
   2497         assert_eq!(
   2498             Manifest::from_toml(
   2499                 "[build-dependencies]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
   2500                 false,
   2501                 Path::new(""),
   2502                 &[]
   2503             ),
   2504             Err(Box::new(ManifestErr::ImpliedFeatures(
   2505                 ImpliedFeaturesErr::Dependencies(DependenciesErr::DependencyType(
   2506                     "build-dependencies",
   2507                     String::new()
   2508                 )),
   2509                 PathBuf::new(),
   2510             )))
   2511         );
   2512         assert_eq!(
   2513             Manifest::from_toml(
   2514                 "[dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
   2515                 false,
   2516                 Path::new(""),
   2517                 &[]
   2518             ),
   2519             Err(Box::new(ManifestErr::ImpliedFeatures(
   2520                 ImpliedFeaturesErr::Dependencies(DependenciesErr::OptionalType(
   2521                     "dependencies",
   2522                     String::new()
   2523                 )),
   2524                 PathBuf::new(),
   2525             )))
   2526         );
   2527         assert_eq!(
   2528             Manifest::from_toml(
   2529                 "[build-dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
   2530                 false,
   2531                 Path::new(""),
   2532                 &[]
   2533             ),
   2534             Err(Box::new(ManifestErr::ImpliedFeatures(
   2535                 ImpliedFeaturesErr::Dependencies(DependenciesErr::OptionalType(
   2536                     "build-dependencies",
   2537                     String::new()
   2538                 )),
   2539                 PathBuf::new(),
   2540             )))
   2541         );
   2542         // Implied features are disallowed iff `!allow_implied_features`.
   2543         assert_eq!(
   2544             Manifest::from_toml(
   2545                 "[dependencies]\nfoo={optional=true}\n[package]\nname=\"\"".to_owned(),
   2546                 false,
   2547                 Path::new(""),
   2548                 &[]
   2549             ),
   2550             Err(Box::new(ManifestErr::ImpliedFeatures(
   2551                 ImpliedFeaturesErr::Dependencies(DependenciesErr::ImpliedFeature(
   2552                     "dependencies",
   2553                     "foo".to_owned()
   2554                 )),
   2555                 PathBuf::new(),
   2556             )))
   2557         );
   2558         assert_eq!(
   2559             Manifest::from_toml(
   2560                 "[target]\n\"\"=2\n[package]\nname=\"\"".to_owned(),
   2561                 false,
   2562                 Path::new(""),
   2563                 &[]
   2564             ),
   2565             Err(Box::new(ManifestErr::ImpliedFeatures(
   2566                 ImpliedFeaturesErr::TargetPlatformType(String::new()),
   2567                 PathBuf::new(),
   2568             )))
   2569         );
   2570         assert_eq!(
   2571             Manifest::from_toml(
   2572                 "[target.\"\"]\ndependencies=2\n[package]\nname=\"\"".to_owned(),
   2573                 false,
   2574                 Path::new(""),
   2575                 &[]
   2576             ),
   2577             Err(Box::new(ManifestErr::ImpliedFeatures(
   2578                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2579                     String::new(),
   2580                     DependenciesErr::Type("dependencies")
   2581                 ),
   2582                 PathBuf::new(),
   2583             )))
   2584         );
   2585         assert_eq!(
   2586             Manifest::from_toml(
   2587                 "[target.\"\"]\nbuild-dependencies=2\n[package]\nname=\"\"".to_owned(),
   2588                 false,
   2589                 Path::new(""),
   2590                 &[]
   2591             ),
   2592             Err(Box::new(ManifestErr::ImpliedFeatures(
   2593                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2594                     String::new(),
   2595                     DependenciesErr::Type("build-dependencies")
   2596                 ),
   2597                 PathBuf::new(),
   2598             )))
   2599         );
   2600         assert_eq!(
   2601             Manifest::from_toml(
   2602                 "[target.\"\".dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2603                 false,
   2604                 Path::new(""),
   2605                 &[]
   2606             ),
   2607             Err(Box::new(ManifestErr::ImpliedFeatures(
   2608                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2609                     String::new(),
   2610                     DependenciesErr::Name("dependencies", "/".to_owned())
   2611                 ),
   2612                 PathBuf::new(),
   2613             )))
   2614         );
   2615         assert_eq!(
   2616             Manifest::from_toml(
   2617                 "[target.\"\".dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2618                 false,
   2619                 Path::new(""),
   2620                 &[]
   2621             ),
   2622             Err(Box::new(ManifestErr::ImpliedFeatures(
   2623                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2624                     String::new(),
   2625                     DependenciesErr::Name("dependencies", "dep:".to_owned())
   2626                 ),
   2627                 PathBuf::new(),
   2628             )))
   2629         );
   2630         assert_eq!(
   2631             Manifest::from_toml(
   2632                 "[target.\"\".build-dependencies]\n\"/\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2633                 false,
   2634                 Path::new(""),
   2635                 &[]
   2636             ),
   2637             Err(Box::new(ManifestErr::ImpliedFeatures(
   2638                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2639                     String::new(),
   2640                     DependenciesErr::Name("build-dependencies", "/".to_owned())
   2641                 ),
   2642                 PathBuf::new(),
   2643             )))
   2644         );
   2645         assert_eq!(
   2646             Manifest::from_toml(
   2647                 "[target.\"\".build-dependencies]\n\"dep:\"=\"\"\n[package]\nname=\"\"".to_owned(),
   2648                 false,
   2649                 Path::new(""),
   2650                 &[]
   2651             ),
   2652             Err(Box::new(ManifestErr::ImpliedFeatures(
   2653                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2654                     String::new(),
   2655                     DependenciesErr::Name("build-dependencies", "dep:".to_owned())
   2656                 ),
   2657                 PathBuf::new(),
   2658             )))
   2659         );
   2660         assert_eq!(
   2661             Manifest::from_toml(
   2662                 "[target.\"\".dependencies]\n\"\"=false\n[package]\nname=\"\"".to_owned(),
   2663                 false,
   2664                 Path::new(""),
   2665                 &[]
   2666             ),
   2667             Err(Box::new(ManifestErr::ImpliedFeatures(
   2668                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2669                     String::new(),
   2670                     DependenciesErr::DependencyType("dependencies", String::new())
   2671                 ),
   2672                 PathBuf::new(),
   2673             )))
   2674         );
   2675         assert_eq!(
   2676             Manifest::from_toml(
   2677                 "[target.\"\".build-dependencies]\n\"\"=false\n[package]\nname=\"\"".to_owned(),
   2678                 false,
   2679                 Path::new(""),
   2680                 &[]
   2681             ),
   2682             Err(Box::new(ManifestErr::ImpliedFeatures(
   2683                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2684                     String::new(),
   2685                     DependenciesErr::DependencyType("build-dependencies", String::new())
   2686                 ),
   2687                 PathBuf::new(),
   2688             )))
   2689         );
   2690         assert_eq!(
   2691             Manifest::from_toml(
   2692                 "[target.\"\".dependencies]\n\"\"={optional=2}\n[package]\nname=\"\"".to_owned(),
   2693                 false,
   2694                 Path::new(""),
   2695                 &[]
   2696             ),
   2697             Err(Box::new(ManifestErr::ImpliedFeatures(
   2698                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2699                     String::new(),
   2700                     DependenciesErr::OptionalType("dependencies", String::new())
   2701                 ),
   2702                 PathBuf::new(),
   2703             )))
   2704         );
   2705         assert_eq!(
   2706             Manifest::from_toml(
   2707                 "[target.\"\".build-dependencies]\n\"\"={optional=2}\n[package]\nname=\"\""
   2708                     .to_owned(),
   2709                 false,
   2710                 Path::new(""),
   2711                 &[]
   2712             ),
   2713             Err(Box::new(ManifestErr::ImpliedFeatures(
   2714                 ImpliedFeaturesErr::TagetPlatformDependencies(
   2715                     String::new(),
   2716                     DependenciesErr::OptionalType("build-dependencies", String::new())
   2717                 ),
   2718                 PathBuf::new(),
   2719             )))
   2720         );
   2721         // An invalid dependency error occurs later when we `allow_implied_features` since
   2722         // implied features aren't added until after feature extraction.
   2723         assert_eq!(
   2724             Manifest::from_toml(
   2725                 "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
   2726                 true,
   2727                 Path::new(""),
   2728                 &[]
   2729             ),
   2730             Err(Box::new(ManifestErr::ImpliedFeatures(
   2731                 ImpliedFeaturesErr::InvalidDependency(String::new(), "foo".to_owned()),
   2732                 PathBuf::new(),
   2733             )))
   2734         );
   2735         // In contrast, above would have erred sooner if `!allow_implied_features`.
   2736         assert_eq!(
   2737             Manifest::from_toml(
   2738                 "[features]\n\"\"=[\"foo\"]\n[package]\nname=\"\"".to_owned(),
   2739                 false,
   2740                 Path::new(""),
   2741                 &[]
   2742             ),
   2743             Err(Box::new(ManifestErr::Features(
   2744                 FeaturesErr::FeatureDependencies(FeatureDependenciesErr::InvalidDependency(
   2745                     String::new(),
   2746                     "foo".to_owned()
   2747                 )),
   2748                 PathBuf::new()
   2749             )))
   2750         );
   2751         assert_eq!(
   2752             Manifest::from_toml(
   2753                 "[package]\nname=\"\"".to_owned(),
   2754                 false,
   2755                 Path::new(""),
   2756                 &["a".to_owned()]
   2757             ),
   2758             Err(Box::new(ManifestErr::UndefinedIgnoreFeature(
   2759                 "a".to_owned(),
   2760                 PathBuf::new()
   2761             )))
   2762         );
   2763         // Even if we forbid implied features, we don't error when a feature is defined
   2764         // with the same name of an implied feature. This is due to simplicity in code
   2765         // and the fact that `cargo` will error anyway.
   2766         //
   2767         // For example once `cargo` is invoked, an error will occur due to duplicate features:
   2768         // the explict feature `foo` and the implied feature from the dependency `foo`.
   2769         assert_eq!(
   2770             Manifest::from_toml(
   2771                 "[dependencies]\nfoo={optional=true}\n[features]\nfoo=[]\n[package]\nname=\"\""
   2772                     .to_owned(),
   2773                 false,
   2774                 Path::new(""),
   2775                 &[]
   2776             ),
   2777             Ok(Manifest {
   2778                 package: Package {
   2779                     msrv: None,
   2780                     name: String::new(),
   2781                 },
   2782                 features: Features(vec![("foo".to_owned(), Vec::new())]),
   2783             })
   2784         );
   2785         // Allow major-only MSRV.
   2786         assert_eq!(
   2787             Manifest::from_toml(
   2788                 "[package]\nname=\"foo\"\nrust-version=\"0\"".to_owned(),
   2789                 false,
   2790                 Path::new(""),
   2791                 &[]
   2792             ),
   2793             Ok(Manifest {
   2794                 package: Package {
   2795                     msrv: Some(Msrv {
   2796                         major: 0,
   2797                         minor: None,
   2798                         patch: None,
   2799                     }),
   2800                     name: "foo".to_owned(),
   2801                 },
   2802                 features: Features(Vec::new()),
   2803             })
   2804         );
   2805         // Allow escapes.
   2806         assert_eq!(
   2807             Manifest::from_toml(
   2808                 "[\"\\u0070ackage\"]\n\"n\\u0061me\"=\"\\u0066oo\"\n\"\\u0072ust-version\"=\"0\\u002E\\u0031\"".to_owned(),
   2809                 false,
   2810                 Path::new(""),
   2811                 &[]
   2812             ),
   2813             Ok(Manifest {
   2814                 package: Package {
   2815                     msrv: Some(Msrv {
   2816                         major: 0,
   2817                         minor: Some(1),
   2818                         patch: None,
   2819                     }),
   2820                     name: "foo".to_owned(),
   2821                 },
   2822                 features: Features(Vec::new()),
   2823             })
   2824         );
   2825         assert_eq!(
   2826             Manifest::from_toml(
   2827                 "[package]\nname=\"\"\nrust-version=\"0.0.0\"".to_owned(),
   2828                 false,
   2829                 Path::new(""),
   2830                 &[]
   2831             ),
   2832             Ok(Manifest {
   2833                 package: Package {
   2834                     msrv: Some(Msrv {
   2835                         major: 0,
   2836                         minor: Some(0),
   2837                         patch: Some(0),
   2838                     }),
   2839                     name: String::new(),
   2840                 },
   2841                 features: Features(Vec::new()),
   2842             })
   2843         );
   2844         // Ignore non `rust-version` keys in `package`. Ignore keys in the root document except `package`,
   2845         // `features`, `dependencies`, `build-dependencies`, and `target`. Ignore keys in
   2846         // `target.<something>` unless the key is `dependencies` or `build-dependencies`. Don't treat
   2847         // `<something>` special in `target.<something>` other than its being a table.
   2848         assert_eq!(
   2849             Manifest::from_toml("dev-dependencies=2\n[package]\nname=\"\"\n\nfoo=2\nrust-version=\"18446744073709551615.18446744073709551615.18446744073709551615\"\n[foo]\nbar=false\n[target.\"\".foo]\nbar=2\n[target.foo]\nbar=false\n[target.dependencies]\nfoo=2\n[target.build-dependencies]\nfoo=false\n[target.dev-dependencies]\nfoo=true\n".to_owned(), false, Path::new(""), &[]),
   2850             Ok(Manifest {
   2851                 package: Package {
   2852                     msrv: Some(Msrv {
   2853                         major: u64::MAX,
   2854                         minor: Some(u64::MAX),
   2855                         patch: Some(u64::MAX),
   2856                     }),
   2857                     name: String::new(),
   2858                 },
   2859                 features: Features(Vec::new()),
   2860             })
   2861         );
   2862         // [package]
   2863         // name = ""
   2864         //
   2865         // ["\u0064ependencies"]
   2866         // "\u0000" = "\u0000"
   2867         // a = { optional = true }
   2868         //
   2869         // ["build-\u0064ependencies"]
   2870         // "\u0000" = { optional = true }
   2871         //
   2872         // [dev-dependencies]
   2873         // buzz = { optional = true }
   2874         //
   2875         // [target."".dependencies]
   2876         // b = { optional = false, foo = 2 }
   2877         // fizz = { optional = true, foo = 3 }
   2878         //
   2879         // [target.a.dependencies]
   2880         // c = { optional = true }
   2881         // wuzz = { optional = true }
   2882         //
   2883         // [features]
   2884         // default = ["bar","dep:lk","a/ak", "a/ak"]
   2885         // bar = ["dep\u003Awuzz"]
   2886         //
   2887         // We allow any and all key names unless it's the features table or a dependency table; in which case
   2888         // key names must not contain `'/'` nor begin with `"dep:"`.
   2889         //
   2890         // The order of features is based on the following hierarchy:
   2891         // * Explict features: lexicographically sorted
   2892         // * dependencies: optional only, lexicographically sorted, only if an explicit feature doesn't exist with
   2893         //   the same name nor any explicit feature contains a dependency named `"dep:<dependecy>"` and we allow
   2894         //   implied features. If such feature exists, we don't error but simply don't add.
   2895         // * build-dependencies: read above.
   2896         // * target.<something>: lexicographically sorted by something, within `something`, `dependencies`
   2897         //   is first using the same methodology as item 2, last `build-dependencies`.
   2898         //
   2899         // Once the order of features is determined, the only feature dependencies that are retained are those
   2900         // that don't contain `'/'` nor begin with `"dep:"`. We don't require dependencies to be defined for
   2901         // feature dependencies that contain `'/'` or begin with `"dep:"`. We don't care about duplicate feature
   2902         // dependencies that contain `'/'`.
   2903         //
   2904         // Based on above, `Features` looks like the following:
   2905         // 1. (bar, [])
   2906         // 2. (default, ["bar"])
   2907         // 3. (a, [])
   2908         // 4. (\x00, [])
   2909         // 5. (fizz, [])
   2910         // 6. (c, [])
   2911         assert_eq!(
   2912             Manifest::from_toml(
   2913                 "[\"\\u0064ependencies\"]\n\"\\u0000\"=\"\\u0000\"\na={optional=true}\n[\"build-\\u0064ependencies\"]\n\"\\u0000\"={optional=true}\n[target.\"\".dependencies]\nb={optional=false,foo=2}\nfizz={optional=true,foo=3}\n[features]\ndefault=[\"bar\",\"dep:lk\",\"a/ak\",\"a/ak\"]\nbar=[\"dep\\u003Awuzz\"]\n[dev-dependencies]\nbuzz={optional=true}\n[target.a.dependencies]\nc={optional=true}\nwuzz={optional=true}\n[package]\nname=\"\"".to_owned(),
   2914                 true,
   2915                 Path::new(""),
   2916                 &[]
   2917             ),
   2918             Ok(Manifest {
   2919                 package: Package {
   2920                     msrv: None,
   2921                     name: String::new(),
   2922                 },
   2923                 features: Features(vec![("bar".to_owned(), Vec::new()), ("default".to_owned(), vec!["bar".to_owned()]), ("a".to_owned(), Vec::new()), ("\0".to_owned(), Vec::new()), ("fizz".to_owned(), Vec::new()), ("c".to_owned(), Vec::new())]),
   2924             })
   2925         );
   2926         // [package]
   2927         // name = ""
   2928         //
   2929         // [dependencies]
   2930         // foo = { "optional" = true }
   2931         // fizz = { "optional" = true }
   2932         //
   2933         // [features]
   2934         // fizz = ["dep:fizz"]
   2935         // bar = ["dep:foo"]
   2936         assert_eq!(
   2937             Manifest::from_toml(
   2938                 "[package]\nname=\"\"\n[dependencies]\nfoo={optional=true}\nfizz={optional=true}\n[features]\nfizz=[\"dep:fizz\"]\nbar=[\"dep:foo\"]".to_owned(),
   2939                 false,
   2940                 Path::new(""),
   2941                 &[]
   2942             ),
   2943             Ok(Manifest {
   2944                 package: Package {
   2945                     msrv: None,
   2946                     name: String::new(),
   2947                 },
   2948                 features: Features(vec![
   2949                     ("bar".to_owned(), Vec::new()),
   2950                     ("fizz".to_owned(), Vec::new())
   2951                 ]),
   2952             })
   2953         );
   2954         // [package]
   2955         // name = ""
   2956         //
   2957         // [dependencies]
   2958         // bar = { "optional" = true }
   2959         //
   2960         // [features]
   2961         // foo = ["bar"]
   2962         assert_eq!(
   2963             Manifest::from_toml(
   2964                 "[package]\nname=\"\"\n[dependencies]\nbar={optional=true}\n[features]\nfoo=[\"bar\"]"
   2965                     .to_owned(),
   2966                 true,
   2967                 Path::new(""),
   2968                 &[]
   2969             ),
   2970             Ok(Manifest {
   2971                 package: Package {
   2972                     msrv: None,
   2973                     name: String::new(),
   2974                 },
   2975                 features: Features(vec![
   2976                     ("foo".to_owned(), vec!["bar".to_owned()]),
   2977                     ("bar".to_owned(), Vec::new()),
   2978                 ]),
   2979             })
   2980         );
   2981         assert_eq!(
   2982             Manifest::from_toml(
   2983                 "[package]\nname=\"\"\n[features]\na=[]\nb=[\"a\"]".to_owned(),
   2984                 false,
   2985                 Path::new(""),
   2986                 &["a".to_owned()]
   2987             ),
   2988             Ok(Manifest {
   2989                 package: Package {
   2990                     msrv: None,
   2991                     name: String::new(),
   2992                 },
   2993                 features: Features(vec![]),
   2994             })
   2995         );
   2996         assert_eq!(
   2997             Manifest::from_toml(
   2998                 "[package]\nname=\"\"\n[features]\na=[]\nb=[\"a\"]".to_owned(),
   2999                 false,
   3000                 Path::new(""),
   3001                 &["b".to_owned()]
   3002             ),
   3003             Ok(Manifest {
   3004                 package: Package {
   3005                     msrv: None,
   3006                     name: String::new(),
   3007                 },
   3008                 features: Features(vec![("a".to_owned(), Vec::new())]),
   3009             })
   3010         );
   3011         assert_eq!(
   3012             Manifest::from_toml(
   3013                 "[package]\nname=\"\"\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]"
   3014                     .to_owned(),
   3015                 true,
   3016                 Path::new(""),
   3017                 &["c".to_owned()]
   3018             ),
   3019             Ok(Manifest {
   3020                 package: Package {
   3021                     msrv: None,
   3022                     name: String::new(),
   3023                 },
   3024                 features: Features(vec![]),
   3025             })
   3026         );
   3027         assert_eq!(
   3028             Manifest::from_toml(
   3029                 "[package]\nname=\"\"\n[dependencies]\nc={optional=true}\n[features]\nb=[\"c\"]"
   3030                     .to_owned(),
   3031                 true,
   3032                 Path::new(""),
   3033                 &["b".to_owned()]
   3034             ),
   3035             Ok(Manifest {
   3036                 package: Package {
   3037                     msrv: None,
   3038                     name: String::new(),
   3039                 },
   3040                 features: Features(vec![("c".to_owned(), Vec::new())]),
   3041             })
   3042         );
   3043     }
   3044     #[expect(clippy::unreachable, reason = "want to crash when there is a bug")]
   3045     #[expect(
   3046         clippy::cognitive_complexity,
   3047         clippy::too_many_lines,
   3048         reason = "want to test for a lot of things"
   3049     )]
   3050     #[test]
   3051     fn power_set() {
   3052         #[cfg(target_pointer_width = "16")]
   3053         let feat_len_one_too_large = 17;
   3054         #[cfg(target_pointer_width = "32")]
   3055         let feat_len_one_too_large = 33;
   3056         #[cfg(target_pointer_width = "64")]
   3057         let feat_len_one_too_large = 65;
   3058         let mut feats = Features(vec![(String::new(), Vec::new()); feat_len_one_too_large]);
   3059         assert_eq!(PowerSet::new(&feats, false), Err(TooManyFeaturesErr));
   3060         #[cfg(target_pointer_width = "16")]
   3061         let max_feat_len = 16;
   3062         #[cfg(target_pointer_width = "32")]
   3063         let max_feat_len = 32;
   3064         #[cfg(target_pointer_width = "64")]
   3065         let max_feat_len = 64;
   3066         feats.0 = vec![(String::new(), Vec::new()); max_feat_len];
   3067         #[cfg(any(
   3068             target_pointer_width = "16",
   3069             target_pointer_width = "32",
   3070             target_pointer_width = "64"
   3071         ))]
   3072         assert_eq!(
   3073             PowerSet::new(&feats, false),
   3074             Ok(Some(PowerSet {
   3075                 feats: feats.0.as_slice(),
   3076                 has_remaining: true,
   3077                 check_overlap: false,
   3078                 idx: usize::MAX,
   3079                 buffer: vec![""; max_feat_len],
   3080                 set: String::new(),
   3081                 skipped_sets_counter: 0,
   3082                 skip_empty_set: false,
   3083             }))
   3084         );
   3085         feats.0 = Vec::new();
   3086         assert_eq!(
   3087             PowerSet::new(&feats, false),
   3088             Ok(Some(PowerSet {
   3089                 feats: feats.0.as_slice(),
   3090                 has_remaining: true,
   3091                 check_overlap: false,
   3092                 idx: 0,
   3093                 buffer: Vec::new(),
   3094                 set: String::new(),
   3095                 skipped_sets_counter: 0,
   3096                 skip_empty_set: false,
   3097             }))
   3098         );
   3099         assert_eq!(PowerSet::new(&feats, true), Ok(None));
   3100         let mut power_set = PowerSet::new(&feats, false)
   3101             .unwrap_or_else(|_e| {
   3102                 unreachable!("not possible since we just verified PowerSet::new returned Ok")
   3103             })
   3104             .unwrap_or_else(|| {
   3105                 unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   3106             });
   3107         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   3108         assert_eq!(power_set.next_set(), Some(""));
   3109         assert_eq!(
   3110             power_set,
   3111             PowerSet {
   3112                 feats: feats.0.as_slice(),
   3113                 has_remaining: false,
   3114                 check_overlap: false,
   3115                 idx: 0,
   3116                 buffer: Vec::new(),
   3117                 set: String::new(),
   3118                 skipped_sets_counter: 0,
   3119                 skip_empty_set: false
   3120             }
   3121         );
   3122         assert_eq!(power_set.next_set(), None);
   3123         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   3124         assert_eq!(
   3125             power_set,
   3126             PowerSet {
   3127                 feats: feats.0.as_slice(),
   3128                 has_remaining: false,
   3129                 check_overlap: false,
   3130                 idx: 0,
   3131                 buffer: Vec::new(),
   3132                 set: String::new(),
   3133                 skipped_sets_counter: 0,
   3134                 skip_empty_set: false
   3135             }
   3136         );
   3137         assert_eq!(power_set.next_set(), None);
   3138         power_set.reset();
   3139         assert_eq!(
   3140             power_set,
   3141             PowerSet {
   3142                 feats: feats.0.as_slice(),
   3143                 has_remaining: true,
   3144                 check_overlap: false,
   3145                 idx: 0,
   3146                 buffer: Vec::new(),
   3147                 set: String::new(),
   3148                 skipped_sets_counter: 0,
   3149                 skip_empty_set: false
   3150             }
   3151         );
   3152         assert_eq!(power_set.next_set(), Some(""));
   3153         assert_eq!(
   3154             power_set,
   3155             PowerSet {
   3156                 feats: feats.0.as_slice(),
   3157                 has_remaining: false,
   3158                 check_overlap: false,
   3159                 idx: 0,
   3160                 buffer: Vec::new(),
   3161                 set: String::new(),
   3162                 skipped_sets_counter: 0,
   3163                 skip_empty_set: false
   3164             }
   3165         );
   3166         assert_eq!(power_set.next_set(), None);
   3167         assert_eq!(
   3168             power_set,
   3169             PowerSet {
   3170                 feats: feats.0.as_slice(),
   3171                 has_remaining: false,
   3172                 check_overlap: false,
   3173                 idx: 0,
   3174                 buffer: Vec::new(),
   3175                 set: String::new(),
   3176                 skipped_sets_counter: 0,
   3177                 skip_empty_set: false
   3178             }
   3179         );
   3180         assert_eq!(power_set.next_set(), None);
   3181         // [features]
   3182         // a = ["b"]
   3183         // b = ["c", "d"]
   3184         // c = []
   3185         // d = []
   3186         feats.0 = vec![
   3187             ("a".to_owned(), vec!["b".to_owned()]),
   3188             ("b".to_owned(), vec!["c".to_owned(), "d".to_owned()]),
   3189             ("c".to_owned(), Vec::new()),
   3190             ("d".to_owned(), Vec::new()),
   3191         ];
   3192         assert_eq!(
   3193             PowerSet::new(&feats, false),
   3194             Ok(Some(PowerSet {
   3195                 feats: feats.0.as_slice(),
   3196                 has_remaining: true,
   3197                 // At least one feature depends on another, so this will be set to `true`.
   3198                 check_overlap: true,
   3199                 idx: 15,
   3200                 buffer: vec!["a", "b", "c", "d"],
   3201                 set: String::new(),
   3202                 skipped_sets_counter: 0,
   3203                 skip_empty_set: false
   3204             }))
   3205         );
   3206         power_set = PowerSet::new(&feats, false)
   3207             .unwrap_or_else(|_e| {
   3208                 unreachable!("not possible since we just verified PowerSet::new returned Ok")
   3209             })
   3210             .unwrap_or_else(|| {
   3211                 unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   3212             });
   3213         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   3214         // Order is the following:
   3215         // 1. a,b,c,d: skipped since a depends on b.
   3216         // 2. b,c,d: skipped since b depends on c.
   3217         // 3. a,c,d: skipped since a depends on c (via b).
   3218         // 4. c,d
   3219         // 5. a,b,d: skipped since a depends on b.
   3220         // 6. b,d: skipped since b depends on d.
   3221         // 7. a,d: skipped since a depends on d (via b).
   3222         // 8. d
   3223         // 9. a,b,c: skipped since a depends on b.
   3224         // 10. b,c: skipped since b depends on c.
   3225         // 11. a,c: skipped since a depends on c (via b).
   3226         // 12. c
   3227         // 13. a,b: skipped since a depends on b.
   3228         // 14. b
   3229         // 15. a
   3230         // 16.
   3231         assert_eq!(power_set.next_set(), Some("c,d"));
   3232         assert_eq!(
   3233             power_set,
   3234             PowerSet {
   3235                 feats: feats.0.as_slice(),
   3236                 has_remaining: true,
   3237                 check_overlap: true,
   3238                 // We started at 15, and we iterated 4 items (skipping 3).
   3239                 idx: 11,
   3240                 buffer: vec!["c", "d"],
   3241                 set: "c,d".to_owned(),
   3242                 skipped_sets_counter: 3,
   3243                 skip_empty_set: false
   3244             }
   3245         );
   3246         assert_eq!(power_set.next_set(), Some("d"));
   3247         assert_eq!(
   3248             power_set,
   3249             PowerSet {
   3250                 feats: feats.0.as_slice(),
   3251                 has_remaining: true,
   3252                 check_overlap: true,
   3253                 // We started at 11, and we iterated 4 items (skipping 3).
   3254                 idx: 7,
   3255                 buffer: vec!["d"],
   3256                 set: "d".to_owned(),
   3257                 skipped_sets_counter: 6,
   3258                 skip_empty_set: false
   3259             }
   3260         );
   3261         assert_eq!(power_set.next_set(), Some("c"));
   3262         assert_eq!(
   3263             power_set,
   3264             PowerSet {
   3265                 feats: feats.0.as_slice(),
   3266                 has_remaining: true,
   3267                 check_overlap: true,
   3268                 // We started at 7, and we iterated 4 items (skipping 3).
   3269                 idx: 3,
   3270                 buffer: vec!["c"],
   3271                 set: "c".to_owned(),
   3272                 skipped_sets_counter: 9,
   3273                 skip_empty_set: false
   3274             }
   3275         );
   3276         assert_eq!(power_set.next_set(), Some("b"));
   3277         assert_eq!(
   3278             power_set,
   3279             PowerSet {
   3280                 feats: feats.0.as_slice(),
   3281                 has_remaining: true,
   3282                 check_overlap: true,
   3283                 // We started at 3, and we iterated 2 items (skipping 1).
   3284                 idx: 1,
   3285                 buffer: vec!["b"],
   3286                 set: "b".to_owned(),
   3287                 skipped_sets_counter: 10,
   3288                 skip_empty_set: false
   3289             }
   3290         );
   3291         assert_eq!(power_set.next_set(), Some("a"));
   3292         assert_eq!(
   3293             power_set,
   3294             PowerSet {
   3295                 feats: feats.0.as_slice(),
   3296                 has_remaining: true,
   3297                 check_overlap: true,
   3298                 // We started at 1, and we iterated 1 item.
   3299                 idx: 0,
   3300                 buffer: vec!["a"],
   3301                 set: "a".to_owned(),
   3302                 skipped_sets_counter: 10,
   3303                 skip_empty_set: false
   3304             }
   3305         );
   3306         assert_eq!(power_set.next_set(), Some(""));
   3307         assert_eq!(
   3308             power_set,
   3309             PowerSet {
   3310                 feats: feats.0.as_slice(),
   3311                 has_remaining: false,
   3312                 check_overlap: true,
   3313                 // We started at 0, and we iterated 1 item but we don't underflow instead `has_remaining` is set
   3314                 // to `false`.
   3315                 idx: 0,
   3316                 buffer: Vec::new(),
   3317                 set: String::new(),
   3318                 skipped_sets_counter: 10,
   3319                 skip_empty_set: false
   3320             }
   3321         );
   3322         assert_eq!(power_set.next_set(), None);
   3323         // Internal state is left unchanged.
   3324         assert_eq!(
   3325             power_set,
   3326             PowerSet {
   3327                 feats: feats.0.as_slice(),
   3328                 has_remaining: false,
   3329                 check_overlap: true,
   3330                 idx: 0,
   3331                 buffer: Vec::new(),
   3332                 set: String::new(),
   3333                 skipped_sets_counter: 10,
   3334                 skip_empty_set: false
   3335             }
   3336         );
   3337         assert_eq!(power_set.next_set(), None);
   3338         // Internal state is left unchanged.
   3339         assert_eq!(
   3340             power_set,
   3341             PowerSet {
   3342                 feats: feats.0.as_slice(),
   3343                 has_remaining: false,
   3344                 check_overlap: true,
   3345                 idx: 0,
   3346                 buffer: Vec::new(),
   3347                 set: String::new(),
   3348                 skipped_sets_counter: 10,
   3349                 skip_empty_set: false
   3350             }
   3351         );
   3352         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   3353         power_set.reset();
   3354         // `PowerSet::reset` only resets what is necessary nothing more; in particular, `buffer` and `set` are
   3355         // left alone.
   3356         assert_eq!(
   3357             power_set,
   3358             PowerSet {
   3359                 feats: feats.0.as_slice(),
   3360                 has_remaining: true,
   3361                 check_overlap: true,
   3362                 idx: 15,
   3363                 buffer: Vec::new(),
   3364                 set: String::new(),
   3365                 skipped_sets_counter: 0,
   3366                 skip_empty_set: false
   3367             }
   3368         );
   3369         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   3370         // Same as above except no feature depends on any other.
   3371         // [features]
   3372         // a = []
   3373         // b = []
   3374         // c = []
   3375         // d = []
   3376         feats.0 = vec![
   3377             ("a".to_owned(), Vec::new()),
   3378             ("b".to_owned(), Vec::new()),
   3379             ("c".to_owned(), Vec::new()),
   3380             ("d".to_owned(), Vec::new()),
   3381         ];
   3382         assert_eq!(
   3383             PowerSet::new(&feats, false),
   3384             Ok(Some(PowerSet {
   3385                 feats: feats.0.as_slice(),
   3386                 has_remaining: true,
   3387                 check_overlap: false,
   3388                 idx: 15,
   3389                 buffer: vec!["a", "b", "c", "d"],
   3390                 set: String::new(),
   3391                 skipped_sets_counter: 0,
   3392                 skip_empty_set: false
   3393             }))
   3394         );
   3395         power_set = PowerSet::new(&feats, false)
   3396             .unwrap_or_else(|_e| {
   3397                 unreachable!("not possible since we just verified PowerSet::new returned Ok")
   3398             })
   3399             .unwrap_or_else(|| {
   3400                 unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   3401             });
   3402         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   3403         // Order is the same as above except nothing is skipped:
   3404         // 1. a,b,c,d
   3405         // 2. b,c,d
   3406         // 3. a,c,d
   3407         // 4. c,d
   3408         // 5. a,b,d
   3409         // 6. b,d
   3410         // 7. a,d
   3411         // 8. d
   3412         // 9. a,b,c
   3413         // 10. b,c
   3414         // 11. a,c
   3415         // 12. c
   3416         // 13. a,b
   3417         // 14. b
   3418         // 15. a
   3419         // 16.
   3420         assert_eq!(power_set.next_set(), Some("a,b,c,d"));
   3421         assert_eq!(
   3422             power_set,
   3423             PowerSet {
   3424                 feats: feats.0.as_slice(),
   3425                 has_remaining: true,
   3426                 check_overlap: false,
   3427                 idx: 14,
   3428                 buffer: vec!["a", "b", "c", "d"],
   3429                 set: "a,b,c,d".to_owned(),
   3430                 skipped_sets_counter: 0,
   3431                 skip_empty_set: false
   3432             }
   3433         );
   3434         assert_eq!(power_set.next_set(), Some("b,c,d"));
   3435         assert_eq!(
   3436             power_set,
   3437             PowerSet {
   3438                 feats: feats.0.as_slice(),
   3439                 has_remaining: true,
   3440                 check_overlap: false,
   3441                 idx: 13,
   3442                 buffer: vec!["b", "c", "d"],
   3443                 set: "b,c,d".to_owned(),
   3444                 skipped_sets_counter: 0,
   3445                 skip_empty_set: false
   3446             }
   3447         );
   3448         assert_eq!(power_set.next_set(), Some("a,c,d"));
   3449         assert_eq!(
   3450             power_set,
   3451             PowerSet {
   3452                 feats: feats.0.as_slice(),
   3453                 has_remaining: true,
   3454                 check_overlap: false,
   3455                 idx: 12,
   3456                 buffer: vec!["a", "c", "d"],
   3457                 set: "a,c,d".to_owned(),
   3458                 skipped_sets_counter: 0,
   3459                 skip_empty_set: false
   3460             }
   3461         );
   3462         assert_eq!(power_set.next_set(), Some("c,d"));
   3463         assert_eq!(
   3464             power_set,
   3465             PowerSet {
   3466                 feats: feats.0.as_slice(),
   3467                 has_remaining: true,
   3468                 check_overlap: false,
   3469                 idx: 11,
   3470                 buffer: vec!["c", "d"],
   3471                 set: "c,d".to_owned(),
   3472                 skipped_sets_counter: 0,
   3473                 skip_empty_set: false
   3474             }
   3475         );
   3476         assert_eq!(power_set.next_set(), Some("a,b,d"));
   3477         assert_eq!(
   3478             power_set,
   3479             PowerSet {
   3480                 feats: feats.0.as_slice(),
   3481                 has_remaining: true,
   3482                 check_overlap: false,
   3483                 idx: 10,
   3484                 buffer: vec!["a", "b", "d"],
   3485                 set: "a,b,d".to_owned(),
   3486                 skipped_sets_counter: 0,
   3487                 skip_empty_set: false
   3488             }
   3489         );
   3490         assert_eq!(power_set.next_set(), Some("b,d"));
   3491         assert_eq!(
   3492             power_set,
   3493             PowerSet {
   3494                 feats: feats.0.as_slice(),
   3495                 has_remaining: true,
   3496                 check_overlap: false,
   3497                 idx: 9,
   3498                 buffer: vec!["b", "d"],
   3499                 set: "b,d".to_owned(),
   3500                 skipped_sets_counter: 0,
   3501                 skip_empty_set: false
   3502             }
   3503         );
   3504         assert_eq!(power_set.next_set(), Some("a,d"));
   3505         assert_eq!(
   3506             power_set,
   3507             PowerSet {
   3508                 feats: feats.0.as_slice(),
   3509                 has_remaining: true,
   3510                 check_overlap: false,
   3511                 idx: 8,
   3512                 buffer: vec!["a", "d"],
   3513                 set: "a,d".to_owned(),
   3514                 skipped_sets_counter: 0,
   3515                 skip_empty_set: false
   3516             }
   3517         );
   3518         assert_eq!(power_set.next_set(), Some("d"));
   3519         assert_eq!(
   3520             power_set,
   3521             PowerSet {
   3522                 feats: feats.0.as_slice(),
   3523                 has_remaining: true,
   3524                 check_overlap: false,
   3525                 idx: 7,
   3526                 buffer: vec!["d"],
   3527                 set: "d".to_owned(),
   3528                 skipped_sets_counter: 0,
   3529                 skip_empty_set: false
   3530             }
   3531         );
   3532         assert_eq!(power_set.next_set(), Some("a,b,c"));
   3533         assert_eq!(
   3534             power_set,
   3535             PowerSet {
   3536                 feats: feats.0.as_slice(),
   3537                 has_remaining: true,
   3538                 check_overlap: false,
   3539                 idx: 6,
   3540                 buffer: vec!["a", "b", "c"],
   3541                 set: "a,b,c".to_owned(),
   3542                 skipped_sets_counter: 0,
   3543                 skip_empty_set: false
   3544             }
   3545         );
   3546         assert_eq!(power_set.next_set(), Some("b,c"));
   3547         assert_eq!(
   3548             power_set,
   3549             PowerSet {
   3550                 feats: feats.0.as_slice(),
   3551                 has_remaining: true,
   3552                 check_overlap: false,
   3553                 idx: 5,
   3554                 buffer: vec!["b", "c"],
   3555                 set: "b,c".to_owned(),
   3556                 skipped_sets_counter: 0,
   3557                 skip_empty_set: false
   3558             }
   3559         );
   3560         assert_eq!(power_set.next_set(), Some("a,c"));
   3561         assert_eq!(
   3562             power_set,
   3563             PowerSet {
   3564                 feats: feats.0.as_slice(),
   3565                 has_remaining: true,
   3566                 check_overlap: false,
   3567                 idx: 4,
   3568                 buffer: vec!["a", "c"],
   3569                 set: "a,c".to_owned(),
   3570                 skipped_sets_counter: 0,
   3571                 skip_empty_set: false
   3572             }
   3573         );
   3574         assert_eq!(power_set.next_set(), Some("c"));
   3575         assert_eq!(
   3576             power_set,
   3577             PowerSet {
   3578                 feats: feats.0.as_slice(),
   3579                 has_remaining: true,
   3580                 check_overlap: false,
   3581                 idx: 3,
   3582                 buffer: vec!["c"],
   3583                 set: "c".to_owned(),
   3584                 skipped_sets_counter: 0,
   3585                 skip_empty_set: false
   3586             }
   3587         );
   3588         assert_eq!(power_set.next_set(), Some("a,b"));
   3589         assert_eq!(
   3590             power_set,
   3591             PowerSet {
   3592                 feats: feats.0.as_slice(),
   3593                 has_remaining: true,
   3594                 check_overlap: false,
   3595                 idx: 2,
   3596                 buffer: vec!["a", "b"],
   3597                 set: "a,b".to_owned(),
   3598                 skipped_sets_counter: 0,
   3599                 skip_empty_set: false
   3600             }
   3601         );
   3602         assert_eq!(power_set.next_set(), Some("b"));
   3603         assert_eq!(
   3604             power_set,
   3605             PowerSet {
   3606                 feats: feats.0.as_slice(),
   3607                 has_remaining: true,
   3608                 check_overlap: false,
   3609                 idx: 1,
   3610                 buffer: vec!["b"],
   3611                 set: "b".to_owned(),
   3612                 skipped_sets_counter: 0,
   3613                 skip_empty_set: false
   3614             }
   3615         );
   3616         assert_eq!(power_set.next_set(), Some("a"));
   3617         assert_eq!(
   3618             power_set,
   3619             PowerSet {
   3620                 feats: feats.0.as_slice(),
   3621                 has_remaining: true,
   3622                 check_overlap: false,
   3623                 idx: 0,
   3624                 buffer: vec!["a"],
   3625                 set: "a".to_owned(),
   3626                 skipped_sets_counter: 0,
   3627                 skip_empty_set: false
   3628             }
   3629         );
   3630         assert_eq!(power_set.next_set(), Some(""));
   3631         assert_eq!(
   3632             power_set,
   3633             PowerSet {
   3634                 feats: feats.0.as_slice(),
   3635                 has_remaining: false,
   3636                 check_overlap: false,
   3637                 idx: 0,
   3638                 buffer: Vec::new(),
   3639                 set: String::new(),
   3640                 skipped_sets_counter: 0,
   3641                 skip_empty_set: false
   3642             }
   3643         );
   3644         assert_eq!(power_set.next_set(), None);
   3645         assert_eq!(
   3646             power_set,
   3647             PowerSet {
   3648                 feats: feats.0.as_slice(),
   3649                 has_remaining: false,
   3650                 check_overlap: false,
   3651                 idx: 0,
   3652                 buffer: Vec::new(),
   3653                 set: String::new(),
   3654                 skipped_sets_counter: 0,
   3655                 skip_empty_set: false
   3656             }
   3657         );
   3658         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(16));
   3659         feats.0 = vec![("a".to_owned(), Vec::new())];
   3660         assert_eq!(
   3661             PowerSet::new(&feats, true),
   3662             Ok(Some(PowerSet {
   3663                 feats: feats.0.as_slice(),
   3664                 has_remaining: true,
   3665                 check_overlap: false,
   3666                 idx: 1,
   3667                 buffer: vec!["a"],
   3668                 set: String::new(),
   3669                 skipped_sets_counter: 0,
   3670                 skip_empty_set: true
   3671             }))
   3672         );
   3673         power_set = PowerSet::new(&feats, true)
   3674             .unwrap_or_else(|_e| {
   3675                 unreachable!("not possible since we just verified PowerSet::new returned Ok")
   3676             })
   3677             .unwrap_or_else(|| {
   3678                 unreachable!("not possible since we just verified PowerSet::new returned Ok(Some)")
   3679             });
   3680         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   3681         assert_eq!(power_set.next_set(), Some("a"));
   3682         assert_eq!(
   3683             power_set,
   3684             PowerSet {
   3685                 feats: feats.0.as_slice(),
   3686                 has_remaining: false,
   3687                 check_overlap: false,
   3688                 idx: 0,
   3689                 buffer: vec!["a"],
   3690                 set: "a".to_owned(),
   3691                 skipped_sets_counter: 0,
   3692                 skip_empty_set: true,
   3693             }
   3694         );
   3695         assert_eq!(power_set.next_set(), None);
   3696         assert_eq!(
   3697             power_set,
   3698             PowerSet {
   3699                 feats: feats.0.as_slice(),
   3700                 has_remaining: false,
   3701                 check_overlap: false,
   3702                 idx: 0,
   3703                 buffer: vec!["a"],
   3704                 set: "a".to_owned(),
   3705                 skipped_sets_counter: 0,
   3706                 skip_empty_set: true,
   3707             }
   3708         );
   3709         assert_eq!(power_set.next_set(), None);
   3710         assert_eq!(
   3711             power_set,
   3712             PowerSet {
   3713                 feats: feats.0.as_slice(),
   3714                 has_remaining: false,
   3715                 check_overlap: false,
   3716                 idx: 0,
   3717                 buffer: vec!["a"],
   3718                 set: "a".to_owned(),
   3719                 skipped_sets_counter: 0,
   3720                 skip_empty_set: true,
   3721             }
   3722         );
   3723         power_set.reset();
   3724         assert_eq!(
   3725             power_set,
   3726             PowerSet {
   3727                 feats: feats.0.as_slice(),
   3728                 has_remaining: true,
   3729                 check_overlap: false,
   3730                 idx: 1,
   3731                 buffer: vec!["a"],
   3732                 set: "a".to_owned(),
   3733                 skipped_sets_counter: 0,
   3734                 skip_empty_set: true,
   3735             }
   3736         );
   3737         assert_eq!(power_set.next_set(), Some("a"));
   3738         assert_eq!(power_set.next_set(), None);
   3739         assert_eq!(
   3740             power_set,
   3741             PowerSet {
   3742                 feats: feats.0.as_slice(),
   3743                 has_remaining: false,
   3744                 check_overlap: false,
   3745                 idx: 0,
   3746                 buffer: vec!["a"],
   3747                 set: "a".to_owned(),
   3748                 skipped_sets_counter: 0,
   3749                 skip_empty_set: true,
   3750             }
   3751         );
   3752         assert_eq!(power_set.len(), NonZeroUsizePlus1::new(1));
   3753     }
   3754 }