just/src/attribute.rs

128 lines
2.8 KiB
Rust
Raw Normal View History

use super::*;
2024-05-25 00:32:25 -07:00
#[derive(
EnumDiscriminants, PartialEq, Debug, Clone, Serialize, Ord, PartialOrd, Eq, IntoStaticStr,
)]
#[strum(serialize_all = "kebab-case")]
#[serde(rename_all = "kebab-case")]
2024-05-25 00:32:25 -07:00
#[strum_discriminants(name(AttributeDiscriminant))]
#[strum_discriminants(derive(EnumString))]
#[strum_discriminants(strum(serialize_all = "kebab-case"))]
pub(crate) enum Attribute<'src> {
Confirm(Option<StringLiteral<'src>>),
2024-05-25 00:32:25 -07:00
Group(StringLiteral<'src>),
Linux,
Macos,
2022-11-02 23:37:35 -07:00
NoCd,
NoExitMessage,
NoQuiet,
2024-05-25 00:32:25 -07:00
Private,
Unix,
Windows,
}
2024-05-25 00:32:25 -07:00
impl AttributeDiscriminant {
fn argument_range(self) -> RangeInclusive<usize> {
match self {
Self::Confirm => 0..=1,
Self::Group => 1..=1,
Self::Linux
| Self::Macos
| Self::NoCd
| Self::NoExitMessage
| Self::NoQuiet
| Self::Private
| Self::Unix
| Self::Windows => 0..=0,
}
}
2024-05-25 00:32:25 -07:00
}
2024-05-25 00:32:25 -07:00
impl<'src> Attribute<'src> {
pub(crate) fn new(
name: Name<'src>,
2024-05-25 00:32:25 -07:00
argument: Option<StringLiteral<'src>>,
) -> CompileResult<'src, Self> {
2024-05-25 00:32:25 -07:00
use AttributeDiscriminant::*;
let discriminant = name
.lexeme()
.parse::<AttributeDiscriminant>()
.ok()
.ok_or_else(|| {
name.error(CompileErrorKind::UnknownAttribute {
attribute: name.lexeme(),
})
})?;
let found = argument.as_ref().iter().count();
let range = discriminant.argument_range();
if !range.contains(&found) {
return Err(
name.error(CompileErrorKind::AttributeArgumentCountMismatch {
attribute: name.lexeme(),
found,
min: *range.start(),
max: *range.end(),
}),
);
}
2024-05-25 00:32:25 -07:00
Ok(match discriminant {
Confirm => Self::Confirm(argument),
Group => Self::Group(argument.unwrap()),
Linux => Self::Linux,
Macos => Self::Macos,
NoCd => Self::NoCd,
NoExitMessage => Self::NoExitMessage,
NoQuiet => Self::NoQuiet,
Private => Self::Private,
Unix => Self::Unix,
Windows => Self::Windows,
})
}
pub(crate) fn name(&self) -> &'static str {
self.into()
}
fn argument(&self) -> Option<&StringLiteral> {
2024-05-25 00:32:25 -07:00
match self {
Self::Confirm(prompt) => prompt.as_ref(),
Self::Group(name) => Some(name),
Self::Linux
| Self::Macos
| Self::NoCd
| Self::NoExitMessage
| Self::NoQuiet
| Self::Private
| Self::Unix
| Self::Windows => None,
}
}
}
impl<'src> Display for Attribute<'src> {
fn fmt(&self, f: &mut Formatter) -> Result<(), fmt::Error> {
write!(f, "{}", self.name())?;
if let Some(argument) = self.argument() {
write!(f, "({argument})")?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn name() {
assert_eq!(Attribute::NoExitMessage.name(), "no-exit-message");
}
}