use pel::expression::Symbol;
use pel::runtime::value::Value as PelValue;
use pel::runtime::{Binding as PelBinding, Context, ValueHandler};
use pel::Reference;
use crate::constants::{
AUTHENTICATION, AUTHENTICATION_REFERENCE, CLIENT_ID, CLIENT_NAME, PRINCIPAL, PROPERTIES,
};
use crate::context::input::InputContext;
use crate::{AuthenticationBinding, Value};
pub(crate) struct AuthenticationContext<'a> {
input_context: &'a InputContext,
authentication: &'a dyn AuthenticationBinding,
}
impl<'a> AuthenticationContext<'a> {
pub fn new(
input_context: &'a InputContext,
authentication: &'a dyn AuthenticationBinding,
) -> Self {
Self {
input_context,
authentication,
}
}
fn client_id(&self) -> Option<PelValue> {
self.authentication.client_id().map(PelValue::string)
}
fn client_name(&self) -> Option<PelValue> {
self.authentication.client_name().map(PelValue::string)
}
fn principal(&self) -> Option<PelValue> {
self.authentication.principal().map(PelValue::string)
}
fn properties(&self) -> Option<PelValue> {
self.authentication.properties().map(Value::into_pel)
}
}
impl Context for AuthenticationContext<'_> {
fn resolve(&self, symbol: &Symbol) -> PelBinding {
match self.input_context.authentication() && symbol.as_str() == AUTHENTICATION {
true => PelBinding::Available(PelValue::reference(AUTHENTICATION_REFERENCE)),
false => PelBinding::Unknown,
}
}
fn value_handler(&self, reference: Reference) -> Option<&dyn ValueHandler> {
match reference {
AUTHENTICATION_REFERENCE => Some(self),
_ => None,
}
}
}
impl ValueHandler for AuthenticationContext<'_> {
fn select_by_key(&self, key: &str) -> Option<PelValue> {
let result = match key {
CLIENT_ID => self.client_id(),
CLIENT_NAME => self.client_name(),
PRINCIPAL => self.principal(),
PROPERTIES => self.properties(),
_ => None,
};
Some(result.unwrap_or_else(PelValue::null))
}
fn detach(&self) -> Option<PelValue> {
let values = [
(CLIENT_ID, self.client_id()),
(CLIENT_NAME, self.client_name()),
(PRINCIPAL, self.principal()),
(PROPERTIES, self.properties()),
]
.map(|(k, v)| (k.to_string(), v.unwrap_or_else(PelValue::null)));
Some(PelValue::object(values.into()))
}
}