use std::fmt::Display;
use std::fmt::Formatter;
use std::ops::Range;
use std::str::FromStr;
use itertools::Itertools;
use super::id::ConnectedElement;
use super::json_selection::SelectionTrie;
use crate::connectors::validation::Code;
#[derive(Clone, PartialEq)]
pub(crate) struct VariableContext<'schema> {
pub(crate) element: &'schema ConnectedElement<'schema>,
pub(super) phase: Phase,
pub(super) target: Target,
}
impl<'schema> VariableContext<'schema> {
pub(crate) const fn new(
element: &'schema ConnectedElement<'schema>,
phase: Phase,
target: Target,
) -> Self {
Self {
element,
phase,
target,
}
}
pub(crate) fn available_namespaces(&self) -> impl Iterator<Item = Namespace> {
match &self.phase {
Phase::Response => {
vec![
Namespace::Args,
Namespace::Config,
Namespace::Context,
Namespace::Status,
Namespace::This,
Namespace::Request,
Namespace::Response,
Namespace::Env,
]
}
}
.into_iter()
}
pub(crate) fn namespaces_joined(&self) -> String {
self.available_namespaces()
.map(|s| s.to_string())
.sorted()
.join(", ")
}
pub(crate) const fn error_code(&self) -> Code {
match self.target {
Target::Body => Code::InvalidSelection,
}
}
}
#[derive(Clone, Copy, PartialEq)]
pub(crate) enum Phase {
Response,
}
#[allow(unused)]
#[derive(Clone, Copy, PartialEq)]
pub(crate) enum Target {
Body,
}
#[derive(PartialEq, Eq, Clone, Copy, Hash)]
pub enum Namespace {
Args,
Config,
Context,
Status,
This,
Batch,
Request,
Response,
Env,
}
impl Namespace {
pub const fn as_str(&self) -> &'static str {
match self {
Self::Args => "$args",
Self::Config => "$config",
Self::Context => "$context",
Self::Status => "$status",
Self::This => "$this",
Self::Batch => "$batch",
Self::Request => "$request",
Self::Response => "$response",
Self::Env => "$env",
}
}
}
impl FromStr for Namespace {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"$args" => Ok(Self::Args),
"$config" => Ok(Self::Config),
"$context" => Ok(Self::Context),
"$status" => Ok(Self::Status),
"$this" => Ok(Self::This),
"$batch" => Ok(Self::Batch),
"$request" => Ok(Self::Request),
"$response" => Ok(Self::Response),
"$env" => Ok(Self::Env),
_ => Err(()),
}
}
}
impl std::fmt::Debug for Namespace {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl Display for Namespace {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.as_str())
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct VariableReference<N: FromStr + ToString> {
pub namespace: VariableNamespace<N>,
pub(crate) selection: SelectionTrie,
pub(crate) location: Option<Range<usize>>,
}
impl<N: FromStr + ToString> Display for VariableReference<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
f.write_str(self.namespace.namespace.to_string().as_str())?;
if !self.selection.is_empty() {
write!(f, " {{ {} }}", self.selection)?;
}
Ok(())
}
}
#[derive(Debug, Eq, PartialEq, Clone, Hash)]
pub struct VariableNamespace<N: FromStr + ToString> {
pub namespace: N,
pub(crate) location: Option<Range<usize>>,
}