#![allow(unused)]
use core::fmt;
use core::mem::discriminant;
use core::ops;
use core::str::FromStr;
use rust_alloc::string::{String, ToString};
use rust_alloc::vec::Vec;
use crate as rune;
use crate::alloc::prelude::*;
use serde::de;
use serde::ser;
pub(crate) use toml::value::{Datetime, DatetimeParseError};
use toml::Spanned;
pub(crate) use linked_hash_map::LinkedHashMap as Map;
pub(crate) type SpannedValue = Spanned<Value>;
#[derive(PartialEq, Clone, Debug)]
pub(crate) enum Value {
String(String),
Integer(i64),
Float(f64),
Boolean(bool),
Datetime(Datetime),
Array(Array),
Table(Table),
}
pub(crate) type Array = Vec<SpannedValue>;
pub(crate) type Table = Map<Spanned<String>, SpannedValue>;
impl Value {
pub(crate) fn get<I: Index>(&self, index: I) -> Option<&SpannedValue> {
index.index(self)
}
pub(crate) fn get_mut<I: Index>(&mut self, index: I) -> Option<&mut SpannedValue> {
index.index_mut(self)
}
pub(crate) fn as_integer(&self) -> Option<i64> {
match *self {
Value::Integer(i) => Some(i),
_ => None,
}
}
pub(crate) fn is_integer(&self) -> bool {
self.as_integer().is_some()
}
pub(crate) fn as_float(&self) -> Option<f64> {
match *self {
Value::Float(f) => Some(f),
_ => None,
}
}
pub(crate) fn is_float(&self) -> bool {
self.as_float().is_some()
}
pub(crate) fn as_bool(&self) -> Option<bool> {
match *self {
Value::Boolean(b) => Some(b),
_ => None,
}
}
pub(crate) fn is_bool(&self) -> bool {
self.as_bool().is_some()
}
pub(crate) fn as_str(&self) -> Option<&str> {
match *self {
Value::String(ref s) => Some(&**s),
_ => None,
}
}
pub(crate) fn is_str(&self) -> bool {
self.as_str().is_some()
}
pub(crate) fn as_datetime(&self) -> Option<&Datetime> {
match *self {
Value::Datetime(ref s) => Some(s),
_ => None,
}
}
pub(crate) fn is_datetime(&self) -> bool {
self.as_datetime().is_some()
}
pub(crate) fn as_array(&self) -> Option<&Vec<SpannedValue>> {
match *self {
Value::Array(ref s) => Some(s),
_ => None,
}
}
pub(crate) fn as_array_mut(&mut self) -> Option<&mut Vec<SpannedValue>> {
match *self {
Value::Array(ref mut s) => Some(s),
_ => None,
}
}
pub(crate) fn is_array(&self) -> bool {
self.as_array().is_some()
}
pub(crate) fn as_table(&self) -> Option<&Table> {
match *self {
Value::Table(ref s) => Some(s),
_ => None,
}
}
pub(crate) fn as_table_mut(&mut self) -> Option<&mut Table> {
match *self {
Value::Table(ref mut s) => Some(s),
_ => None,
}
}
pub(crate) fn is_table(&self) -> bool {
self.as_table().is_some()
}
pub(crate) fn same_type(&self, other: &Value) -> bool {
discriminant(self) == discriminant(other)
}
pub(crate) fn type_str(&self) -> &'static str {
match *self {
Value::String(..) => "string",
Value::Integer(..) => "integer",
Value::Float(..) => "float",
Value::Boolean(..) => "boolean",
Value::Datetime(..) => "datetime",
Value::Array(..) => "array",
Value::Table(..) => "table",
}
}
}
impl<I> ops::Index<I> for Value
where
I: Index,
{
type Output = SpannedValue;
fn index(&self, index: I) -> &SpannedValue {
self.get(index).expect("index not found")
}
}
impl<I> ops::IndexMut<I> for Value
where
I: Index,
{
fn index_mut(&mut self, index: I) -> &mut SpannedValue {
self.get_mut(index).expect("index not found")
}
}
impl From<&str> for Value {
#[inline]
fn from(string: &str) -> Value {
Value::String(string.to_string())
}
}
impl<V> From<Vec<V>> for Value
where
V: Into<SpannedValue>,
{
fn from(val: Vec<V>) -> Value {
Value::Array(val.into_iter().map(|v| v.into()).collect())
}
}
macro_rules! impl_into_value {
($variant:ident : $T:ty) => {
impl From<$T> for Value {
#[inline]
fn from(val: $T) -> Value {
Value::$variant(val.into())
}
}
};
}
impl_into_value!(String: String);
impl_into_value!(Integer: i64);
impl_into_value!(Integer: i32);
impl_into_value!(Integer: i8);
impl_into_value!(Integer: u8);
impl_into_value!(Integer: u32);
impl_into_value!(Float: f64);
impl_into_value!(Float: f32);
impl_into_value!(Boolean: bool);
impl_into_value!(Datetime: Datetime);
impl_into_value!(Table: Table);
pub(crate) trait Index: Sealed {
#[doc(hidden)]
fn index<'a>(&self, val: &'a Value) -> Option<&'a SpannedValue>;
#[doc(hidden)]
fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut SpannedValue>;
}
#[doc(hidden)]
pub(crate) trait Sealed {}
impl Sealed for usize {}
impl Sealed for str {}
impl Sealed for String {}
impl<T: ?Sized + Sealed> Sealed for &T {}
impl Index for usize {
fn index<'a>(&self, val: &'a Value) -> Option<&'a SpannedValue> {
match *val {
Value::Array(ref a) => a.get(*self),
_ => None,
}
}
fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut SpannedValue> {
match *val {
Value::Array(ref mut a) => a.get_mut(*self),
_ => None,
}
}
}
impl Index for str {
fn index<'a>(&self, val: &'a Value) -> Option<&'a SpannedValue> {
match *val {
Value::Table(ref a) => a.get(self),
_ => None,
}
}
fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut SpannedValue> {
match *val {
Value::Table(ref mut a) => a.get_mut(self),
_ => None,
}
}
}
impl Index for String {
fn index<'a>(&self, val: &'a Value) -> Option<&'a SpannedValue> {
self[..].index(val)
}
fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut SpannedValue> {
self[..].index_mut(val)
}
}
impl<T> Index for &T
where
T: ?Sized + Index,
{
fn index<'a>(&self, val: &'a Value) -> Option<&'a SpannedValue> {
(**self).index(val)
}
fn index_mut<'a>(&self, val: &'a mut Value) -> Option<&'a mut SpannedValue> {
(**self).index_mut(val)
}
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
toml::ser::to_string(self)
.expect("Unable to represent value as string")
.fmt(f)
}
}
impl FromStr for Value {
type Err = toml::de::Error;
fn from_str(s: &str) -> Result<Value, Self::Err> {
toml::from_str(s)
}
}
impl ser::Serialize for Value {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: ser::Serializer,
{
use serde::ser::SerializeMap;
match *self {
Value::String(ref s) => serializer.serialize_str(s),
Value::Integer(i) => serializer.serialize_i64(i),
Value::Float(f) => serializer.serialize_f64(f),
Value::Boolean(b) => serializer.serialize_bool(b),
Value::Datetime(ref s) => s.serialize(serializer),
Value::Array(ref a) => a.serialize(serializer),
Value::Table(ref t) => {
let mut map = serializer.serialize_map(Some(t.len()))?;
for (k, v) in t {
if !v.get_ref().is_table() && !v.get_ref().is_array()
|| (v
.get_ref()
.as_array()
.map(|a| !a.iter().any(|v| v.get_ref().is_table()))
.unwrap_or(false))
{
map.serialize_entry(k, v)?;
}
}
for (k, v) in t {
if v.get_ref()
.as_array()
.map(|a| a.iter().any(|v| v.get_ref().is_table()))
.unwrap_or(false)
{
map.serialize_entry(k, v)?;
}
}
for (k, v) in t {
if v.get_ref().is_table() {
map.serialize_entry(k, v)?;
}
}
map.end()
}
}
}
}
impl<'de> de::Deserialize<'de> for Value {
fn deserialize<D>(deserializer: D) -> Result<Value, D::Error>
where
D: de::Deserializer<'de>,
{
struct MutableValueVisitor;
impl<'de> de::Visitor<'de> for MutableValueVisitor {
type Value = Value;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("any valid TOML value")
}
fn visit_bool<E>(self, value: bool) -> Result<Value, E> {
Ok(Value::Boolean(value))
}
fn visit_i64<E>(self, value: i64) -> Result<Value, E> {
Ok(Value::Integer(value))
}
fn visit_u64<E>(self, value: u64) -> Result<Value, E>
where
E: de::Error,
{
if let Ok(value) = i64::try_from(value) {
return Ok(Value::Integer(value));
}
Err(de::Error::custom("u64 value was too large"))
}
fn visit_u32<E>(self, value: u32) -> Result<Value, E> {
Ok(Value::Integer(value.into()))
}
fn visit_i32<E>(self, value: i32) -> Result<Value, E> {
Ok(Value::Integer(value.into()))
}
fn visit_f64<E>(self, value: f64) -> Result<Value, E> {
Ok(Value::Float(value))
}
fn visit_str<E>(self, value: &str) -> Result<Value, E>
where
E: de::Error,
{
Ok(Value::String(value.to_string()))
}
fn visit_string<E>(self, value: String) -> Result<Value, E>
where
E: de::Error,
{
Ok(Value::String(value))
}
fn visit_some<D>(self, deserializer: D) -> Result<Value, D::Error>
where
D: de::Deserializer<'de>,
{
de::Deserialize::deserialize(deserializer)
}
fn visit_seq<V>(self, mut visitor: V) -> Result<Value, V::Error>
where
V: de::SeqAccess<'de>,
{
let mut vec = Vec::new();
while let Some(elem) = visitor.next_element()? {
vec.push(elem);
}
Ok(Value::Array(vec))
}
fn visit_map<V>(self, mut visitor: V) -> Result<Value, V::Error>
where
V: de::MapAccess<'de>,
{
let key = visitor.next_key_seed(DatetimeOrTable)?;
let key = match key {
Some(Some(key)) => key,
Some(None) => {
let date: DatetimeFromString = visitor.next_value()?;
return Ok(Value::Datetime(date.value));
}
None => return Ok(Value::Table(Map::new())),
};
let mut map = Map::new();
map.insert(key, visitor.next_value()?);
while let Some(key) = visitor.next_key()? {
if map.contains_key(&key) {
let key: Spanned<String> = key;
let msg = format!("duplicate key: `{}`", key.get_ref());
return Err(de::Error::custom(msg));
}
map.insert(key, visitor.next_value()?);
}
Ok(Value::Table(map))
}
}
deserializer.deserialize_any(MutableValueVisitor)
}
}
struct DatetimeFromString {
pub(crate) value: Datetime,
}
impl<'de> de::Deserialize<'de> for DatetimeFromString {
fn deserialize<D>(deserializer: D) -> Result<DatetimeFromString, D::Error>
where
D: de::Deserializer<'de>,
{
struct Visitor;
impl de::Visitor<'_> for Visitor {
type Value = DatetimeFromString;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("string containing a datetime")
}
fn visit_str<E>(self, s: &str) -> Result<DatetimeFromString, E>
where
E: de::Error,
{
match s.parse() {
Ok(date) => Ok(DatetimeFromString { value: date }),
Err(e) => Err(de::Error::custom(e)),
}
}
}
deserializer.deserialize_str(Visitor)
}
}
#[derive(Debug)]
struct OptError<E: de::Error>(Option<E>);
impl<E: de::Error> core::error::Error for OptError<E> {}
impl<E: de::Error> core::fmt::Display for OptError<E> {
fn fmt(&self, _fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
unreachable!()
}
}
impl<E: de::Error> de::Error for OptError<E> {
fn custom<T: core::fmt::Display>(msg: T) -> Self {
Self(Some(<E as de::Error>::custom(msg)))
}
}
struct LayerDeserializer<'de, D: de::Deserializer<'de>>(D, std::marker::PhantomData<&'de ()>);
impl<'de, D: de::Deserializer<'de>> de::Deserializer<'de> for LayerDeserializer<'de, D> {
type Error = OptError<D::Error>;
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
self.0
.deserialize_any(visitor)
.map_err(|e| OptError(Some(e)))
}
fn deserialize_struct<V>(
self,
name: &'static str,
fields: &'static [&'static str],
visitor: V,
) -> Result<V::Value, Self::Error>
where
V: de::Visitor<'de>,
{
let wrapped_visitor = DatetimeOrTableWrapper(visitor);
match self.0.deserialize_struct(name, fields, wrapped_visitor) {
Ok(Some(v)) => Ok(v),
Ok(None) => Err(OptError(None)),
Err(v) => Err(OptError(Some(v))),
}
}
serde::forward_to_deserialize_any! {
bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
bytes byte_buf option unit unit_struct newtype_struct seq tuple
tuple_struct map enum identifier ignored_any
}
}
struct DatetimeOrTable;
impl<'de> de::DeserializeSeed<'de> for DatetimeOrTable {
type Value = Option<Spanned<String>>;
fn deserialize<D>(self, deserializer: D) -> Result<Self::Value, D::Error>
where
D: de::Deserializer<'de>,
{
let deserializer = LayerDeserializer(deserializer, std::marker::PhantomData);
let res = <Spanned<String> as de::Deserialize<'_>>::deserialize(deserializer);
match res {
Ok(v) => Ok(Some(v)),
Err(OptError(None)) => Ok(None),
Err(OptError(Some(e))) => Err(e),
}
}
}
struct DatetimeOrTableWrapper<V>(V);
impl<'de, V: de::Visitor<'de>> de::Visitor<'de> for DatetimeOrTableWrapper<V> {
type Value = Option<V::Value>;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_str("a string key")
}
fn visit_map<W>(self, visitor: W) -> Result<Self::Value, W::Error>
where
W: de::MapAccess<'de>,
{
let key = self.0.visit_map(visitor)?;
Ok(Some(key))
}
fn visit_str<E>(self, _s: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
fn visit_string<E>(self, _s: rust_alloc::string::String) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(None)
}
}