use std::borrow::Cow;
use std::cell::RefCell;
use std::collections::{BTreeMap, HashMap, HashSet};
use std::convert::TryFrom;
use std::ops::{Deref, DerefMut};
use crate::error::{Error, ErrorKind};
use crate::key::{Key, StaticKey};
use crate::utils::UndefinedBehavior;
use crate::value::{
Arc, MapType, Object, Packed, SeqObject, StringType, Value, ValueKind, ValueMap, ValueRepr,
};
use crate::vm::State;
pub trait FunctionResult {
#[doc(hidden)]
fn into_result(self) -> Result<Value, Error>;
}
impl<I: Into<Value>> FunctionResult for Result<I, Error> {
fn into_result(self) -> Result<Value, Error> {
self.map(Into::into)
}
}
impl<I: Into<Value>> FunctionResult for I {
fn into_result(self) -> Result<Value, Error> {
Ok(self.into())
}
}
pub trait FunctionArgs<'a> {
type Output;
#[doc(hidden)]
fn from_values(state: Option<&'a State>, values: &'a [Value]) -> Result<Self::Output, Error>;
}
#[inline(always)]
pub fn from_args<'a, Args>(values: &'a [Value]) -> Result<Args, Error>
where
Args: FunctionArgs<'a, Output = Args>,
{
Args::from_values(None, values)
}
pub trait ArgType<'a> {
type Output;
#[doc(hidden)]
fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error>;
#[doc(hidden)]
fn from_value_owned(_value: Value) -> Result<Self::Output, Error> {
Err(Error::new(
ErrorKind::InvalidOperation,
"type conversion is not legal in this situation (implicit borrow)",
))
}
#[doc(hidden)]
fn from_state_and_value(
state: Option<&'a State>,
value: Option<&'a Value>,
) -> Result<(Self::Output, usize), Error> {
if value.map_or(false, |x| x.is_undefined())
&& state.map_or(false, |x| {
matches!(x.undefined_behavior(), UndefinedBehavior::Strict)
})
{
Err(Error::from(ErrorKind::UndefinedError))
} else {
Ok((ok!(Self::from_value(value)), 1))
}
}
#[doc(hidden)]
#[inline(always)]
fn from_state_and_values(
state: Option<&'a State>,
values: &'a [Value],
offset: usize,
) -> Result<(Self::Output, usize), Error> {
Self::from_state_and_value(state, values.get(offset))
}
}
macro_rules! tuple_impls {
( $( $name:ident )* * $rest_name:ident ) => {
impl<'a, $($name,)* $rest_name> FunctionArgs<'a> for ($($name,)* $rest_name,)
where $($name: ArgType<'a>,)* $rest_name: ArgType<'a>
{
type Output = ($($name::Output,)* $rest_name::Output ,);
fn from_values(state: Option<&'a State>, values: &'a [Value]) -> Result<Self::Output, Error> {
#![allow(non_snake_case, unused)]
let mut idx = 0;
$(
let ($name, offset) = ok!($name::from_state_and_value(state, values.get(idx)));
idx += offset;
)*
let ($rest_name, offset) = ok!($rest_name::from_state_and_values(state, values, idx));
idx += offset;
if values.get(idx).is_some() {
Err(Error::from(ErrorKind::TooManyArguments))
} else {
Ok(( $($name,)* $rest_name,))
}
}
}
};
}
impl<'a> FunctionArgs<'a> for () {
type Output = ();
fn from_values(_state: Option<&'a State>, values: &'a [Value]) -> Result<Self::Output, Error> {
if values.is_empty() {
Ok(())
} else {
Err(Error::from(ErrorKind::TooManyArguments))
}
}
}
tuple_impls! { *A }
tuple_impls! { A *B }
tuple_impls! { A B *C }
tuple_impls! { A B C *D }
tuple_impls! { A B C D *E }
impl From<ValueRepr> for Value {
#[inline(always)]
fn from(val: ValueRepr) -> Value {
Value(val)
}
}
impl<'a> From<&'a [u8]> for Value {
#[inline(always)]
fn from(val: &'a [u8]) -> Self {
ValueRepr::Bytes(Arc::new(val.into())).into()
}
}
impl<'a> From<&'a str> for Value {
#[inline(always)]
fn from(val: &'a str) -> Self {
ValueRepr::String(Arc::new(val.into()), StringType::Normal).into()
}
}
impl From<String> for Value {
#[inline(always)]
fn from(val: String) -> Self {
ValueRepr::String(Arc::new(val), StringType::Normal).into()
}
}
impl<'a> From<Cow<'a, str>> for Value {
#[inline(always)]
fn from(val: Cow<'a, str>) -> Self {
match val {
Cow::Borrowed(x) => x.into(),
Cow::Owned(x) => x.into(),
}
}
}
impl From<()> for Value {
#[inline(always)]
fn from(_: ()) -> Self {
ValueRepr::None.into()
}
}
impl<'a> From<Key<'a>> for Value {
fn from(val: Key) -> Self {
match val {
Key::Bool(val) => val.into(),
Key::I64(val) => val.into(),
Key::Char(val) => val.into(),
Key::String(val) => ValueRepr::String(val, StringType::Normal).into(),
Key::Str(val) => val.into(),
}
}
}
impl<V: Into<Value>> FromIterator<V> for Value {
fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
let vec = iter.into_iter().map(|v| v.into()).collect();
ValueRepr::Seq(Arc::new(vec)).into()
}
}
impl<K: Into<StaticKey>, V: Into<Value>> FromIterator<(K, V)> for Value {
fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
let map = iter
.into_iter()
.map(|(k, v)| (k.into(), v.into()))
.collect();
ValueRepr::Map(Arc::new(map), MapType::Normal).into()
}
}
impl<K: Into<StaticKey>, V: Into<Value>> From<BTreeMap<K, V>> for Value {
fn from(val: BTreeMap<K, V>) -> Self {
val.into_iter().map(|(k, v)| (k.into(), v.into())).collect()
}
}
impl<K: Into<StaticKey>, V: Into<Value>> From<HashMap<K, V>> for Value {
fn from(val: HashMap<K, V>) -> Self {
val.into_iter().map(|(k, v)| (k.into(), v.into())).collect()
}
}
impl<T: Into<Value>> From<Vec<T>> for Value {
fn from(val: Vec<T>) -> Self {
val.into_iter().map(|v| v.into()).collect()
}
}
impl<T: Object> From<Arc<T>> for Value {
fn from(object: Arc<T>) -> Self {
Value::from(object as Arc<dyn Object>)
}
}
impl From<Arc<String>> for Value {
fn from(value: Arc<String>) -> Self {
Value(ValueRepr::String(value, StringType::Normal))
}
}
macro_rules! value_from {
($src:ty, $dst:ident) => {
impl From<$src> for Value {
#[inline(always)]
fn from(val: $src) -> Self {
ValueRepr::$dst(val as _).into()
}
}
};
}
impl From<i128> for Value {
#[inline(always)]
fn from(val: i128) -> Self {
ValueRepr::I128(Packed(val)).into()
}
}
impl From<u128> for Value {
#[inline(always)]
fn from(val: u128) -> Self {
ValueRepr::U128(Packed(val)).into()
}
}
value_from!(bool, Bool);
value_from!(u8, U64);
value_from!(u16, U64);
value_from!(u32, U64);
value_from!(u64, U64);
value_from!(i8, I64);
value_from!(i16, I64);
value_from!(i32, I64);
value_from!(i64, I64);
value_from!(f32, F64);
value_from!(f64, F64);
value_from!(char, Char);
value_from!(Arc<Vec<u8>>, Bytes);
value_from!(Arc<Vec<Value>>, Seq);
value_from!(Arc<dyn Object>, Dynamic);
fn unsupported_conversion(kind: ValueKind, target: &str) -> Error {
Error::new(
ErrorKind::InvalidOperation,
format!("cannot convert {kind} to {target}"),
)
}
macro_rules! primitive_try_from {
($ty:ident, {
$($pat:pat $(if $if_expr:expr)? => $expr:expr,)*
}) => {
impl TryFrom<Value> for $ty {
type Error = Error;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.0 {
$($pat $(if $if_expr)? => TryFrom::try_from($expr).ok(),)*
_ => None
}.ok_or_else(|| unsupported_conversion(value.kind(), stringify!($ty)))
}
}
impl<'a> ArgType<'a> for $ty {
type Output = Self;
fn from_value(value: Option<&Value>) -> Result<Self, Error> {
match value {
Some(value) => TryFrom::try_from(value.clone()),
None => Err(Error::from(ErrorKind::MissingArgument))
}
}
fn from_value_owned(value: Value) -> Result<Self, Error> {
TryFrom::try_from(value)
}
}
}
}
macro_rules! primitive_int_try_from {
($ty:ident) => {
primitive_try_from!($ty, {
ValueRepr::Bool(val) => val as usize,
ValueRepr::I64(val) => val,
ValueRepr::U64(val) => val,
ValueRepr::F64(val) if (val as i64 as f64 == val) => val as i64,
ValueRepr::I128(val) => val.0,
ValueRepr::U128(val) => val.0,
});
}
}
primitive_int_try_from!(u8);
primitive_int_try_from!(u16);
primitive_int_try_from!(u32);
primitive_int_try_from!(u64);
primitive_int_try_from!(u128);
primitive_int_try_from!(i8);
primitive_int_try_from!(i16);
primitive_int_try_from!(i32);
primitive_int_try_from!(i64);
primitive_int_try_from!(i128);
primitive_int_try_from!(usize);
primitive_try_from!(bool, {
ValueRepr::Bool(val) => val,
});
primitive_try_from!(char, {
ValueRepr::Char(val) => val,
});
primitive_try_from!(f32, {
ValueRepr::U64(val) => val as f32,
ValueRepr::I64(val) => val as f32,
ValueRepr::U128(val) => val.0 as f32,
ValueRepr::I128(val) => val.0 as f32,
ValueRepr::F64(val) => val as f32,
});
primitive_try_from!(f64, {
ValueRepr::U64(val) => val as f64,
ValueRepr::I64(val) => val as f64,
ValueRepr::U128(val) => val.0 as f64,
ValueRepr::I128(val) => val.0 as f64,
ValueRepr::F64(val) => val,
});
impl<'a> ArgType<'a> for &str {
type Output = &'a str;
fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
match value {
Some(value) => value
.as_str()
.ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "value is not a string")),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
}
impl<'a> ArgType<'a> for &[u8] {
type Output = &'a [u8];
fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
match value {
Some(value) => value
.as_bytes()
.ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "value is not in bytes")),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
}
impl<'a> ArgType<'a> for &dyn SeqObject {
type Output = &'a dyn SeqObject;
fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
match value {
Some(value) => value
.as_seq()
.ok_or_else(|| Error::new(ErrorKind::InvalidOperation, "value is not a sequence")),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
}
impl<'a, T: ArgType<'a>> ArgType<'a> for Option<T> {
type Output = Option<T::Output>;
fn from_value(value: Option<&'a Value>) -> Result<Self::Output, Error> {
match value {
Some(value) => {
if value.is_undefined() {
Ok(None)
} else {
T::from_value(Some(value)).map(Some)
}
}
None => Ok(None),
}
}
fn from_value_owned(value: Value) -> Result<Self::Output, Error> {
if value.is_undefined() || value.is_none() {
Ok(None)
} else {
T::from_value_owned(value).map(Some)
}
}
}
impl<'a> ArgType<'a> for Cow<'_, str> {
type Output = Cow<'a, str>;
#[inline(always)]
fn from_value(value: Option<&'a Value>) -> Result<Cow<'a, str>, Error> {
match value {
Some(value) => Ok(match value.0 {
ValueRepr::String(ref s, _) => Cow::Borrowed(s.as_str()),
_ => Cow::Owned(value.to_string()),
}),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
}
impl<'a> ArgType<'a> for &Value {
type Output = &'a Value;
#[inline(always)]
fn from_value(value: Option<&'a Value>) -> Result<&'a Value, Error> {
match value {
Some(value) => Ok(value),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
}
#[derive(Debug)]
pub struct Rest<T>(pub Vec<T>);
impl<T> Deref for Rest<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for Rest<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'a, T: ArgType<'a, Output = T>> ArgType<'a> for Rest<T> {
type Output = Self;
fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
Ok(Rest(ok!(value
.iter()
.map(|v| T::from_value(Some(v)))
.collect::<Result<_, _>>())))
}
fn from_state_and_values(
_state: Option<&'a State>,
values: &'a [Value],
offset: usize,
) -> Result<(Self, usize), Error> {
let args = values.get(offset..).unwrap_or_default();
Ok((
Rest(ok!(args
.iter()
.map(|v| T::from_value(Some(v)))
.collect::<Result<_, _>>())),
args.len(),
))
}
}
#[derive(Debug, Clone)]
pub struct Kwargs {
values: Arc<ValueMap>,
used: RefCell<HashSet<String>>,
}
impl<'a> ArgType<'a> for Kwargs {
type Output = Self;
fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
match value {
Some(value) => {
if let ValueRepr::Map(ref map, MapType::Kwargs) = value.0 {
Ok(Kwargs::new(map.clone()))
} else {
Err(Error::from(ErrorKind::MissingArgument))
}
}
None => Ok(Kwargs::new(Default::default())),
}
}
fn from_state_and_values(
_state: Option<&'a State>,
values: &'a [Value],
offset: usize,
) -> Result<(Self, usize), Error> {
if let Some(value) = values.get(offset) {
if let ValueRepr::Map(ref map, MapType::Kwargs) = value.0 {
return Ok((Kwargs::new(map.clone()), 1));
}
}
Ok((Kwargs::new(Default::default()), 0))
}
}
impl Kwargs {
fn new(map: Arc<ValueMap>) -> Kwargs {
Kwargs {
values: map,
used: RefCell::new(HashSet::new()),
}
}
pub fn from_args(args: &[Value]) -> (&[Value], Kwargs) {
if let Some(value) = args.last() {
if let ValueRepr::Map(ref map, MapType::Kwargs) = value.0 {
return (&args[..args.len() - 1], Kwargs::new(map.clone()));
}
}
(args, Kwargs::new(Default::default()))
}
pub fn peek<'a, T>(&'a self, key: &'a str) -> Result<T, Error>
where
T: ArgType<'a, Output = T>,
{
T::from_value(self.values.get(&Key::Str(key)))
}
pub fn get<'a, T>(&'a self, key: &'a str) -> Result<T, Error>
where
T: ArgType<'a, Output = T>,
{
let rv = ok!(self.peek::<T>(key));
self.used.borrow_mut().insert(key.to_string());
Ok(rv)
}
pub fn has(&self, key: &str) -> bool {
self.values.contains_key(&Key::Str(key))
}
pub fn args(&self) -> impl Iterator<Item = &str> {
self.values.iter().filter_map(|x| x.0.as_str())
}
pub fn assert_all_used(&self) -> Result<(), Error> {
let used = self.used.borrow();
for key in self.values.keys() {
if let Some(key) = key.as_str() {
if !used.contains(key) {
return Err(Error::new(
ErrorKind::TooManyArguments,
format!("unknown keyword argument '{}'", key),
));
}
} else {
return Err(Error::new(
ErrorKind::InvalidOperation,
"non string keys passed to kwargs",
));
}
}
Ok(())
}
}
impl From<Kwargs> for Value {
fn from(value: Kwargs) -> Self {
Value(ValueRepr::Map(value.values, MapType::Kwargs))
}
}
impl TryFrom<Value> for Kwargs {
type Error = Error;
fn try_from(value: Value) -> Result<Self, Self::Error> {
match value.0 {
ValueRepr::Undefined => Ok(Kwargs::new(Default::default())),
ValueRepr::Map(ref val, MapType::Kwargs) => Ok(Kwargs::new(val.clone())),
_ => Err(Error::from(ErrorKind::InvalidOperation)),
}
}
}
impl<'a> ArgType<'a> for Value {
type Output = Self;
fn from_state_and_value(
_state: Option<&'a State>,
value: Option<&'a Value>,
) -> Result<(Self::Output, usize), Error> {
Ok((ok!(Self::from_value(value)), 1))
}
fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
match value {
Some(value) => Ok(value.clone()),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
fn from_value_owned(value: Value) -> Result<Self, Error> {
Ok(value)
}
}
impl<'a> ArgType<'a> for String {
type Output = Self;
fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
match value {
Some(value) => Ok(value.to_string()),
None => Err(Error::from(ErrorKind::MissingArgument)),
}
}
fn from_value_owned(value: Value) -> Result<Self, Error> {
Ok(value.to_string())
}
}
impl<'a, T: ArgType<'a, Output = T>> ArgType<'a> for Vec<T> {
type Output = Vec<T>;
fn from_value(value: Option<&'a Value>) -> Result<Self, Error> {
match value {
None => Ok(Vec::new()),
Some(value) => {
let seq = ok!(value
.as_seq()
.ok_or_else(|| { Error::new(ErrorKind::InvalidOperation, "not a sequence") }));
let mut rv = Vec::new();
for value in seq.iter() {
rv.push(ok!(T::from_value_owned(value)));
}
Ok(rv)
}
}
}
fn from_value_owned(value: Value) -> Result<Self, Error> {
let seq = ok!(value
.as_seq()
.ok_or_else(|| { Error::new(ErrorKind::InvalidOperation, "not a sequence") }));
let mut rv = Vec::new();
for value in seq.iter() {
rv.push(ok!(T::from_value_owned(value)));
}
Ok(rv)
}
}
impl From<Value> for String {
fn from(val: Value) -> Self {
val.to_string()
}
}
impl From<usize> for Value {
fn from(val: usize) -> Self {
Value::from(val as u64)
}
}
#[test]
fn test_as_f64() {
let v = Value::from(42u32);
let f: f64 = v.try_into().unwrap();
assert_eq!(f, 42.0);
let v = Value::from(42.5);
let f: f64 = v.try_into().unwrap();
assert_eq!(f, 42.5);
}