use super::{BooleanValue, ComposeScalar, FieldReference, Located};
use crate::source::SourceSpan;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnvironmentListEntry {
raw: Located<String>,
name: String,
value: Option<String>,
}
impl EnvironmentListEntry {
pub(super) fn parse(raw: Located<String>) -> Self {
let (name, value) = raw.value().split_once('=').map_or_else(
|| (raw.value().clone(), None),
|(name, value)| (name.to_owned(), Some(value.to_owned())),
);
Self { raw, name, value }
}
#[must_use]
pub const fn raw(&self) -> &Located<String> {
&self.raw
}
#[must_use]
pub fn name(&self) -> &str {
&self.name
}
#[must_use]
pub fn value(&self) -> Option<&str> {
self.value.as_deref()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnvironmentMapEntry {
name: Located<String>,
value: Located<ComposeScalar>,
span: SourceSpan,
}
impl EnvironmentMapEntry {
pub(super) const fn new(name: Located<String>, value: Located<ComposeScalar>, span: SourceSpan) -> Self {
Self { name, value, span }
}
#[must_use]
pub const fn name(&self) -> &Located<String> {
&self.name
}
#[must_use]
pub const fn value(&self) -> &Located<ComposeScalar> {
&self.value
}
#[must_use]
pub const fn span(&self) -> SourceSpan {
self.span
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Environment {
List {
span: SourceSpan,
entries: Vec<EnvironmentListEntry>,
},
Map {
span: SourceSpan,
entries: Vec<EnvironmentMapEntry>,
},
}
impl Environment {
#[must_use]
pub const fn span(&self) -> SourceSpan {
match self {
Self::List { span, .. } | Self::Map { span, .. } => *span,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum EnvironmentFile {
Short(Located<String>),
Long(Box<LongEnvironmentFile>),
}
impl EnvironmentFile {
#[must_use]
pub const fn path(&self) -> Option<&Located<String>> {
match self {
Self::Short(path) => Some(path),
Self::Long(value) => value.path(),
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LongEnvironmentFile {
span: SourceSpan,
path: Option<Located<String>>,
required: Option<Located<BooleanValue>>,
format: Option<EnvironmentFileFormat>,
extension_fields: Vec<FieldReference>,
unknown_fields: Vec<FieldReference>,
}
impl LongEnvironmentFile {
pub(super) const fn new(span: SourceSpan) -> Self {
Self {
span,
path: None,
required: None,
format: None,
extension_fields: Vec::new(),
unknown_fields: Vec::new(),
}
}
pub(super) fn set_path(&mut self, value: Located<String>) {
self.path = Some(value);
}
pub(super) fn set_required(&mut self, value: Located<BooleanValue>) {
self.required = Some(value);
}
pub(super) fn set_format(&mut self, value: EnvironmentFileFormat) {
self.format = Some(value);
}
pub(super) fn push_extension(&mut self, value: FieldReference) {
self.extension_fields.push(value);
}
pub(super) fn push_unknown(&mut self, value: FieldReference) {
self.unknown_fields.push(value);
}
#[must_use]
pub const fn span(&self) -> SourceSpan {
self.span
}
#[must_use]
pub const fn path(&self) -> Option<&Located<String>> {
self.path.as_ref()
}
#[must_use]
pub const fn required(&self) -> Option<&Located<BooleanValue>> {
self.required.as_ref()
}
#[must_use]
pub const fn format(&self) -> Option<&EnvironmentFileFormat> {
self.format.as_ref()
}
#[must_use]
pub fn extension_fields(&self) -> &[FieldReference] {
&self.extension_fields
}
#[must_use]
pub fn unknown_fields(&self) -> &[FieldReference] {
&self.unknown_fields
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EnvironmentFileFormat {
raw: Located<String>,
kind: EnvironmentFileFormatKind,
}
impl EnvironmentFileFormat {
pub(crate) fn parse(raw: Located<String>) -> Self {
let kind = EnvironmentFileFormatKind::classify(raw.value());
Self { raw, kind }
}
#[must_use]
pub const fn raw(&self) -> &Located<String> {
&self.raw
}
#[must_use]
pub const fn kind(&self) -> EnvironmentFileFormatKind {
self.kind
}
#[must_use]
pub const fn is_valid(&self) -> bool {
!matches!(self.kind, EnvironmentFileFormatKind::Other)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[non_exhaustive]
pub enum EnvironmentFileFormatKind {
Raw,
Expression,
Other,
}
impl EnvironmentFileFormatKind {
pub(crate) fn classify(value: &str) -> Self {
match value {
"raw" => Self::Raw,
value if value.contains('$') => Self::Expression,
_ => Self::Other,
}
}
}