use bumpalo::Bump;
use datavalue::OwnedDataValue;
use crate::Result;
use crate::arena::DataValue;
pub(crate) mod sealed {
use bumpalo::Bump;
use crate::arena::DataValue;
pub trait Sealed {}
pub trait LendArena: Sized {
fn lend_arena<R>(
self,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> crate::Result<R>,
) -> crate::Result<R>;
#[inline]
fn lend_arena_for<R>(
self,
logic: &crate::Logic,
engine: &crate::Engine,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> crate::Result<R>,
) -> crate::Result<R> {
let _ = (logic, engine);
self.lend_arena(f)
}
}
#[inline]
pub(crate) fn one_shot_arena() -> Bump {
Bump::with_capacity(4096)
}
}
pub trait EvalInput<'a>: sealed::Sealed {
fn into_arena_value(self, arena: &'a Bump) -> Result<&'a DataValue<'a>>;
#[doc(hidden)]
#[inline]
fn into_arena_for(
self,
logic: &crate::Logic,
engine: &crate::Engine,
arena: &'a Bump,
) -> Result<&'a DataValue<'a>>
where
Self: Sized,
{
let _ = (logic, engine);
self.into_arena_value(arena)
}
}
impl<'a> sealed::Sealed for &'a DataValue<'a> {}
impl<'a> EvalInput<'a> for &'a DataValue<'a> {
#[inline]
fn into_arena_value(self, _arena: &'a Bump) -> Result<&'a DataValue<'a>> {
Ok(self)
}
}
impl<'a> sealed::Sealed for DataValue<'a> {}
impl<'a> EvalInput<'a> for DataValue<'a> {
#[inline]
fn into_arena_value(self, arena: &'a Bump) -> Result<&'a DataValue<'a>> {
Ok(arena.alloc(self))
}
}
impl sealed::Sealed for &str {}
impl<'a> EvalInput<'a> for &'a str {
#[inline]
fn into_arena_value(self, arena: &'a Bump) -> Result<&'a DataValue<'a>> {
let av = DataValue::from_str(self, arena)?;
Ok(arena.alloc(av))
}
}
impl sealed::Sealed for &String {}
impl<'a> EvalInput<'a> for &'a String {
#[inline]
fn into_arena_value(self, arena: &'a Bump) -> Result<&'a DataValue<'a>> {
<&'a str as EvalInput<'a>>::into_arena_value(self.as_str(), arena)
}
}
impl sealed::Sealed for &OwnedDataValue {}
impl<'a> EvalInput<'a> for &'a OwnedDataValue {
#[inline]
fn into_arena_value(self, arena: &'a Bump) -> Result<&'a DataValue<'a>> {
Ok(arena.alloc(self.view_in(arena)))
}
#[inline]
fn into_arena_for(
self,
logic: &crate::Logic,
engine: &crate::Engine,
arena: &'a Bump,
) -> Result<&'a DataValue<'a>> {
Ok(arena.alloc(match logic.projection_for(engine) {
Some(projection) => projection.owned(self, arena),
None => self.view_in(arena),
}))
}
}
impl sealed::Sealed for &crate::ParsedData {}
impl<'a> EvalInput<'a> for &'a crate::ParsedData {
#[inline]
fn into_arena_value(self, _arena: &'a Bump) -> Result<&'a DataValue<'a>> {
Ok(self.value())
}
}
#[cfg(feature = "serde_json")]
impl sealed::Sealed for &serde_json::Value {}
#[cfg(feature = "serde_json")]
impl<'a> EvalInput<'a> for &'a serde_json::Value {
#[inline]
fn into_arena_value(self, arena: &'a Bump) -> Result<&'a DataValue<'a>> {
let av = crate::arena::value_to_data(self, arena);
Ok(arena.alloc(av))
}
#[inline]
fn into_arena_for(
self,
logic: &crate::Logic,
engine: &crate::Engine,
arena: &'a Bump,
) -> Result<&'a DataValue<'a>> {
Ok(arena.alloc(match logic.projection_for(engine) {
Some(projection) => projection.serde(self, arena),
None => crate::arena::value_to_data(self, arena),
}))
}
}
#[cfg_attr(
feature = "serde_json",
doc = "/ [`crate::Engine::eval_into`] and the module-level `datalogic_rs::eval*`"
)]
#[cfg_attr(
not(feature = "serde_json"),
doc = "(plus `Engine::eval_into` with the `serde_json` feature) and the module-level `datalogic_rs::eval*`"
)]
pub trait OwnedInput: sealed::Sealed + sealed::LendArena {
fn into_owned_input(self) -> Result<OwnedDataValue>;
}
impl sealed::LendArena for &str {
#[inline]
fn lend_arena<R>(
self,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
let arena = sealed::one_shot_arena();
let data = arena.alloc(DataValue::from_str(self, &arena)?);
f(data, &arena)
}
}
impl OwnedInput for &str {
#[inline]
fn into_owned_input(self) -> Result<OwnedDataValue> {
Ok(OwnedDataValue::from_json(self)?)
}
}
impl sealed::LendArena for &String {
#[inline]
fn lend_arena<R>(
self,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
self.as_str().lend_arena(f)
}
}
impl OwnedInput for &String {
#[inline]
fn into_owned_input(self) -> Result<OwnedDataValue> {
Ok(OwnedDataValue::from_json(self.as_str())?)
}
}
impl sealed::LendArena for &OwnedDataValue {
#[inline]
fn lend_arena<R>(
self,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
let arena = sealed::one_shot_arena();
let data = arena.alloc(self.view_in(&arena));
f(data, &arena)
}
#[inline]
fn lend_arena_for<R>(
self,
logic: &crate::Logic,
engine: &crate::Engine,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
let arena = sealed::one_shot_arena();
let data = EvalInput::into_arena_for(self, logic, engine, &arena)?;
f(data, &arena)
}
}
impl OwnedInput for &OwnedDataValue {
#[inline]
fn into_owned_input(self) -> Result<OwnedDataValue> {
Ok(self.clone())
}
}
impl sealed::Sealed for OwnedDataValue {}
impl sealed::LendArena for OwnedDataValue {
#[inline]
fn lend_arena<R>(
self,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
(&self).lend_arena(f)
}
#[inline]
fn lend_arena_for<R>(
self,
logic: &crate::Logic,
engine: &crate::Engine,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
(&self).lend_arena_for(logic, engine, f)
}
}
impl OwnedInput for OwnedDataValue {
#[inline]
fn into_owned_input(self) -> Result<OwnedDataValue> {
Ok(self)
}
}
#[cfg(feature = "serde_json")]
impl sealed::LendArena for &serde_json::Value {
#[inline]
fn lend_arena<R>(
self,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
let arena = sealed::one_shot_arena();
let data = arena.alloc(crate::arena::value_to_data(self, &arena));
f(data, &arena)
}
#[inline]
fn lend_arena_for<R>(
self,
logic: &crate::Logic,
engine: &crate::Engine,
f: impl for<'a> FnOnce(&'a DataValue<'a>, &'a Bump) -> Result<R>,
) -> Result<R> {
let arena = sealed::one_shot_arena();
let data = EvalInput::into_arena_for(self, logic, engine, &arena)?;
f(data, &arena)
}
}
#[cfg(feature = "serde_json")]
impl OwnedInput for &serde_json::Value {
#[inline]
fn into_owned_input(self) -> Result<OwnedDataValue> {
Ok(crate::serde_bridge::owned_from_serde(self))
}
}