mirror of
https://codeberg.org/icewind/vdf-reader.git
synced 2026-06-03 10:04:08 +02:00
allow deserializing from Entry
This commit is contained in:
parent
6643822671
commit
ebb940847d
12 changed files with 973 additions and 8 deletions
|
|
@ -1,4 +1,6 @@
|
||||||
use super::Entry;
|
use super::Entry;
|
||||||
|
use crate::VdfError;
|
||||||
|
use serde::de::{DeserializeSeed, SeqAccess};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
|
|
@ -37,3 +39,31 @@ impl DerefMut for Array {
|
||||||
&mut self.0
|
&mut self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct ArraySeq {
|
||||||
|
iter: std::vec::IntoIter<Entry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ArraySeq {
|
||||||
|
pub(crate) fn new(array: Array) -> Self {
|
||||||
|
ArraySeq {
|
||||||
|
iter: array.0.into_iter(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> SeqAccess<'de> for ArraySeq {
|
||||||
|
type Error = VdfError;
|
||||||
|
|
||||||
|
fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
|
||||||
|
where
|
||||||
|
T: DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
let next = match self.iter.next() {
|
||||||
|
Some(next) => next,
|
||||||
|
None => return Ok(None),
|
||||||
|
};
|
||||||
|
|
||||||
|
seed.deserialize(next).map(Some)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
380
src/entry/mod.rs
380
src/entry/mod.rs
|
|
@ -3,8 +3,8 @@ mod statement;
|
||||||
mod table;
|
mod table;
|
||||||
mod value;
|
mod value;
|
||||||
|
|
||||||
use crate::error::{ParseEntryError, ParseItemError, ParseStringError};
|
use crate::error::{ParseEntryError, ParseItemError, ParseStringError, UnknownError};
|
||||||
use crate::Item;
|
use crate::{Item, VdfError};
|
||||||
pub use array::Array;
|
pub use array::Array;
|
||||||
pub use statement::Statement;
|
pub use statement::Statement;
|
||||||
use std::any::type_name;
|
use std::any::type_name;
|
||||||
|
|
@ -177,7 +177,9 @@ macro_rules! from_str {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
use serde::de::{Error, MapAccess, SeqAccess, Visitor};
|
use crate::entry::array::ArraySeq;
|
||||||
|
use crate::entry::table::TableSeq;
|
||||||
|
use serde::de::{DeserializeSeed, EnumAccess, Error, MapAccess, SeqAccess, VariantAccess, Visitor};
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
|
||||||
from_str!(for IpAddr Ipv4Addr Ipv6Addr SocketAddr SocketAddrV4 SocketAddrV6);
|
from_str!(for IpAddr Ipv4Addr Ipv6Addr SocketAddr SocketAddrV4 SocketAddrV6);
|
||||||
|
|
@ -330,6 +332,378 @@ impl<'de> Deserialize<'de> for Entry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserializer<'de> for Entry {
|
||||||
|
type Error = VdfError;
|
||||||
|
|
||||||
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Table(table) => visitor.visit_map(TableSeq::new(table)),
|
||||||
|
Entry::Array(array) => visitor.visit_seq(ArraySeq::new(array)),
|
||||||
|
Entry::Value(val) => val.deserialize_any(visitor),
|
||||||
|
Entry::Statement(val) => visitor.visit_string(val.into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_bool(visitor),
|
||||||
|
_ => Err(UnknownError::from("bool").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_i8(visitor),
|
||||||
|
_ => Err(UnknownError::from("i8").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_i16(visitor),
|
||||||
|
_ => Err(UnknownError::from("i16").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_i32(visitor),
|
||||||
|
_ => Err(UnknownError::from("i32").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_i64(visitor),
|
||||||
|
_ => Err(UnknownError::from("i64").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_u8(visitor),
|
||||||
|
_ => Err(UnknownError::from("u8").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_u16(visitor),
|
||||||
|
_ => Err(UnknownError::from("u16").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_u32(visitor),
|
||||||
|
_ => Err(UnknownError::from("u32").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_u64(visitor),
|
||||||
|
_ => Err(UnknownError::from("u64").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_f32(visitor),
|
||||||
|
_ => Err(UnknownError::from("f32").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_f64(visitor),
|
||||||
|
_ => Err(UnknownError::from("f64").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_char(visitor),
|
||||||
|
Entry::Statement(val) => Value::from(val).deserialize_char(visitor),
|
||||||
|
_ => Err(UnknownError::from("char").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_str(visitor),
|
||||||
|
Entry::Statement(val) => Value::from(val).deserialize_str(visitor),
|
||||||
|
_ => Err(UnknownError::from("str").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_string(visitor),
|
||||||
|
Entry::Statement(val) => Value::from(val).deserialize_string(visitor),
|
||||||
|
_ => Err(UnknownError::from("string1").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_bytes(visitor),
|
||||||
|
_ => Err(UnknownError::from("bytes").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_bool(visitor),
|
||||||
|
_ => Err(UnknownError::from("bytes buf").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_option(visitor),
|
||||||
|
Entry::Statement(val) => Value::from(val).deserialize_option(visitor),
|
||||||
|
_ => Err(UnknownError::from("option").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_unit(visitor),
|
||||||
|
Entry::Statement(val) => Value::from(val).deserialize_unit(visitor),
|
||||||
|
_ => Err(UnknownError::from("unit").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit_struct<V>(
|
||||||
|
self,
|
||||||
|
name: &'static str,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Value(val) => val.deserialize_unit_struct(name, visitor),
|
||||||
|
_ => Err(UnknownError::from("unit_struct").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_newtype_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Array(arr) => visitor.visit_seq(ArraySeq::new(arr)),
|
||||||
|
_ => Err(UnknownError::from("array2").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Array(arr) => visitor.visit_seq(ArraySeq::new(arr)),
|
||||||
|
_ => Err(UnknownError::from("tuple").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Array(arr) => visitor.visit_seq(ArraySeq::new(arr)),
|
||||||
|
_ => Err(UnknownError::from("tuple_struct").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Entry::Table(table) => visitor.visit_map(TableSeq::new(table)),
|
||||||
|
_ => Err(UnknownError::from("map").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_map(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
struct EnVarAccess {
|
||||||
|
variant: Value,
|
||||||
|
value: Entry,
|
||||||
|
}
|
||||||
|
struct EnValAccess {
|
||||||
|
value: Entry,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> EnumAccess<'de> for EnVarAccess {
|
||||||
|
type Error = VdfError;
|
||||||
|
type Variant = EnValAccess;
|
||||||
|
|
||||||
|
fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error>
|
||||||
|
where
|
||||||
|
V: DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
seed.deserialize(self.variant)
|
||||||
|
.map(|v| (v, EnValAccess { value: self.value }))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> VariantAccess<'de> for EnValAccess {
|
||||||
|
type Error = VdfError;
|
||||||
|
|
||||||
|
fn unit_variant(self) -> Result<(), Self::Error> {
|
||||||
|
Err(UnknownError::from("unit").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
|
||||||
|
where
|
||||||
|
T: DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
seed.deserialize(self.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.value.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn struct_variant<V>(
|
||||||
|
self,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.value.deserialize_map(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Entry::Table(table) if table.len() == 1 => {
|
||||||
|
let (variant, value) = HashMap::from(table).into_iter().next().unwrap();
|
||||||
|
visitor.visit_enum(EnVarAccess {
|
||||||
|
variant: variant.into(),
|
||||||
|
value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => Err(UnknownError::from("enum").into()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_string(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_any(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
|
fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
use super::{Array, Entry};
|
use super::{Array, Entry};
|
||||||
use crate::entry::{Statement, Value};
|
use crate::entry::{Statement, Value};
|
||||||
|
use crate::error::UnknownError;
|
||||||
use crate::event::{EntryEvent, GroupStartEvent};
|
use crate::event::{EntryEvent, GroupStartEvent};
|
||||||
use crate::{Event, Item, Reader, Result};
|
use crate::{Event, Item, Reader, Result, VdfError};
|
||||||
|
use serde::de::{DeserializeSeed, MapAccess};
|
||||||
use serde::{Deserialize, Serialize, Serializer};
|
use serde::{Deserialize, Serialize, Serializer};
|
||||||
use std::collections::hash_map;
|
use std::collections::hash_map;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
@ -53,6 +55,11 @@ fn insert<K: Into<String>, V: Into<Entry>>(map: &mut HashMap<String, Entry>, key
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Table {
|
impl Table {
|
||||||
|
pub fn load_from_str(input: &str) -> Result<Table> {
|
||||||
|
let mut reader = Reader::from(input);
|
||||||
|
Self::load(&mut reader)
|
||||||
|
}
|
||||||
|
|
||||||
/// Load a table from the given `Reader`.
|
/// Load a table from the given `Reader`.
|
||||||
pub fn load(reader: &mut Reader) -> Result<Table> {
|
pub fn load(reader: &mut Reader) -> Result<Table> {
|
||||||
let mut map = HashMap::new();
|
let mut map = HashMap::new();
|
||||||
|
|
@ -89,6 +96,12 @@ impl From<Table> for Entry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Table> for HashMap<String, Entry> {
|
||||||
|
fn from(table: Table) -> Self {
|
||||||
|
table.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Deref for Table {
|
impl Deref for Table {
|
||||||
type Target = HashMap<String, Entry>;
|
type Target = HashMap<String, Entry>;
|
||||||
|
|
||||||
|
|
@ -97,6 +110,50 @@ impl Deref for Table {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct TableSeq {
|
||||||
|
iter: hash_map::IntoIter<String, Entry>,
|
||||||
|
next_item: Option<Entry>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TableSeq {
|
||||||
|
pub(crate) fn new(table: Table) -> Self {
|
||||||
|
TableSeq {
|
||||||
|
iter: table.0.into_iter(),
|
||||||
|
next_item: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'de> MapAccess<'de> for TableSeq {
|
||||||
|
type Error = VdfError;
|
||||||
|
|
||||||
|
fn next_key_seed<K>(&mut self, seed: K) -> std::result::Result<Option<K::Value>, Self::Error>
|
||||||
|
where
|
||||||
|
K: DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
let (key, value) = match self.iter.next() {
|
||||||
|
Some(pair) => pair,
|
||||||
|
None => {
|
||||||
|
return Ok(None);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
self.next_item = Some(value);
|
||||||
|
seed.deserialize(Value::from(key)).map(Some)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn next_value_seed<V>(&mut self, seed: V) -> std::result::Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: DeserializeSeed<'de>,
|
||||||
|
{
|
||||||
|
let item = match self.next_item.take() {
|
||||||
|
Some(item) => item,
|
||||||
|
None => return Err(UnknownError::from("double take value").into()),
|
||||||
|
};
|
||||||
|
|
||||||
|
seed.deserialize(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
|
fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,7 @@
|
||||||
use super::Entry;
|
use super::Entry;
|
||||||
|
use crate::entry::{ParseItem, Statement};
|
||||||
|
use crate::error::{ParseStringError, SerdeParseError};
|
||||||
|
use crate::VdfError;
|
||||||
use serde::de::{Error, Visitor};
|
use serde::de::{Error, Visitor};
|
||||||
use serde::{Deserialize, Deserializer, Serialize};
|
use serde::{Deserialize, Deserializer, Serialize};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
@ -26,6 +29,12 @@ impl From<String> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<Statement> for Value {
|
||||||
|
fn from(value: Statement) -> Value {
|
||||||
|
Value(value.into())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Value> for Entry {
|
impl From<Value> for Entry {
|
||||||
fn from(value: Value) -> Self {
|
fn from(value: Value) -> Self {
|
||||||
Entry::Value(value)
|
Entry::Value(value)
|
||||||
|
|
@ -46,6 +55,13 @@ impl Deref for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Value {
|
||||||
|
/// Try to convert the entry to the given type.
|
||||||
|
pub fn to<T: ParseItem>(self) -> Result<T, ParseStringError> {
|
||||||
|
T::from_str(&self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'de> Deserialize<'de> for Value {
|
impl<'de> Deserialize<'de> for Value {
|
||||||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
|
||||||
where
|
where
|
||||||
|
|
@ -107,6 +123,260 @@ impl<'de> Deserialize<'de> for Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'de> Deserializer<'de> for Value {
|
||||||
|
type Error = VdfError;
|
||||||
|
|
||||||
|
fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
if let Ok(int) = i64::from_str(&self.0) {
|
||||||
|
return visitor.visit_i64(int);
|
||||||
|
}
|
||||||
|
if let Ok(float) = f64::from_str(&self.0) {
|
||||||
|
return visitor.visit_f64(float);
|
||||||
|
}
|
||||||
|
if self.0.starts_with('[') && self.0.ends_with(']') {
|
||||||
|
return self.deserialize_seq(visitor);
|
||||||
|
}
|
||||||
|
visitor.visit_string(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_bool(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_i8(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_i16(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_i32(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_i64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_i64(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u8<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_u8(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u16<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_u16(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_u32(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_u64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_u64(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f32<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_f32(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_f64<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_f64(self.to()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
let mut chars = self.0.chars();
|
||||||
|
match (chars.next(), chars.next()) {
|
||||||
|
(Some(_), None) => Ok(()),
|
||||||
|
_ => Err(SerdeParseError::new("char", &self.0, 0..0, "")),
|
||||||
|
}?;
|
||||||
|
|
||||||
|
visitor.visit_str(&self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_str(&self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_string(self.0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_bytes(self.0.as_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_byte_buf(self.0.into_bytes())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
if self.0.is_empty() {
|
||||||
|
return visitor.visit_none();
|
||||||
|
}
|
||||||
|
visitor.visit_some(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
if !self.0.is_empty() {
|
||||||
|
return Err(SerdeParseError::new("unit", self.0.as_ref(), 0..0, "").into());
|
||||||
|
}
|
||||||
|
visitor.visit_unit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_unit_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
if !self.0.is_empty() {
|
||||||
|
return Err(SerdeParseError::new("unit", self.0.as_ref(), 0..0, "").into());
|
||||||
|
}
|
||||||
|
visitor.visit_unit()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_newtype_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
visitor.visit_newtype_struct(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_seq<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(SerdeParseError::new("seq", self.0.as_ref(), 0..0, "").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_tuple_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_len: usize,
|
||||||
|
visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_seq(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_map<V>(self, _visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(SerdeParseError::new("map", self.0.as_ref(), 0..0, "").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_struct<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_fields: &'static [&'static str],
|
||||||
|
_visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(SerdeParseError::new("struct", self.0.as_ref(), 0..0, "").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_enum<V>(
|
||||||
|
self,
|
||||||
|
_name: &'static str,
|
||||||
|
_variants: &'static [&'static str],
|
||||||
|
_visitor: V,
|
||||||
|
) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
Err(SerdeParseError::new("map", self.0.as_ref(), 0..0, "").into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_str(visitor)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
|
||||||
|
where
|
||||||
|
V: Visitor<'de>,
|
||||||
|
{
|
||||||
|
self.deserialize_any(visitor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[track_caller]
|
#[track_caller]
|
||||||
fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
|
fn unwrap_err<T>(r: Result<T, crate::VdfError>) -> T {
|
||||||
|
|
@ -121,3 +391,9 @@ fn test_serde_value() {
|
||||||
let j = r#""foo bar""#;
|
let j = r#""foo bar""#;
|
||||||
assert_eq!(Value("foo bar".into()), unwrap_err(crate::from_str(j)));
|
assert_eq!(Value("foo bar".into()), unwrap_err(crate::from_str(j)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_serde_from_value() {
|
||||||
|
let j = Value::from("1");
|
||||||
|
assert_eq!(true, unwrap_err(crate::from_entry(j.into())));
|
||||||
|
}
|
||||||
|
|
|
||||||
10
src/error.rs
10
src/error.rs
|
|
@ -171,6 +171,16 @@ pub struct UnknownError {
|
||||||
src: String,
|
src: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&str> for UnknownError {
|
||||||
|
fn from(value: &str) -> Self {
|
||||||
|
UnknownError {
|
||||||
|
error: value.to_string(),
|
||||||
|
err_span: (0..0).into(),
|
||||||
|
src: String::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A token that wasn't expected was found while parsing
|
/// A token that wasn't expected was found while parsing
|
||||||
#[derive(Debug, Clone, Diagnostic)]
|
#[derive(Debug, Clone, Diagnostic)]
|
||||||
#[diagnostic(code(vmt_reader::unexpected_token))]
|
#[diagnostic(code(vmt_reader::unexpected_token))]
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@ mod tokenizer;
|
||||||
pub use error::VdfError;
|
pub use error::VdfError;
|
||||||
|
|
||||||
pub type Result<T, E = VdfError> = std::result::Result<T, E>;
|
pub type Result<T, E = VdfError> = std::result::Result<T, E>;
|
||||||
pub use crate::serde::from_str;
|
pub use crate::serde::{from_entry, from_str};
|
||||||
pub use event::{EntryEvent, Event, GroupEndEvent, GroupStartEvent, Item};
|
pub use event::{EntryEvent, Event, GroupEndEvent, GroupStartEvent, Item};
|
||||||
pub use lexer::Token;
|
pub use lexer::Token;
|
||||||
pub use reader::Reader;
|
pub use reader::Reader;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::entry::ParseItem;
|
use crate::entry::{Entry, ParseItem};
|
||||||
use crate::error::{ExpectToken, NoValidTokenError, ResultExt, SerdeParseError};
|
use crate::error::{ExpectToken, NoValidTokenError, ResultExt, SerdeParseError};
|
||||||
use crate::tokenizer::{SpannedToken, Tokenizer};
|
use crate::tokenizer::{SpannedToken, Tokenizer};
|
||||||
use crate::{Token, VdfError};
|
use crate::{Token, VdfError};
|
||||||
|
|
@ -92,6 +92,13 @@ where
|
||||||
T::deserialize(&mut deserializer)
|
T::deserialize(&mut deserializer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_entry<'a, T>(entry: Entry) -> Result<T>
|
||||||
|
where
|
||||||
|
T: Deserialize<'a>,
|
||||||
|
{
|
||||||
|
T::deserialize(entry)
|
||||||
|
}
|
||||||
|
|
||||||
const VALUE_TOKEN: &[Token] = &[
|
const VALUE_TOKEN: &[Token] = &[
|
||||||
Token::Item,
|
Token::Item,
|
||||||
Token::QuotedItem,
|
Token::QuotedItem,
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use std::collections::BTreeMap;
|
||||||
use std::fs::read_to_string;
|
use std::fs::read_to_string;
|
||||||
use test_case::test_case;
|
use test_case::test_case;
|
||||||
use vdf_reader::entry::Table;
|
use vdf_reader::entry::Table;
|
||||||
use vdf_reader::from_str;
|
use vdf_reader::{from_entry, from_str};
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
enum Expected {
|
enum Expected {
|
||||||
|
|
@ -197,7 +197,9 @@ fn test_serde(path: &str) {
|
||||||
fn test_serde_table(path: &str) {
|
fn test_serde_table(path: &str) {
|
||||||
let raw = read_to_string(path).unwrap();
|
let raw = read_to_string(path).unwrap();
|
||||||
match from_str::<Table>(&raw) {
|
match from_str::<Table>(&raw) {
|
||||||
Ok(result) => insta::assert_ron_snapshot!(format!("table__{}", path), result),
|
Ok(result) => {
|
||||||
|
insta::assert_ron_snapshot!(format!("table__{}", path), result);
|
||||||
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
let handler = GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor());
|
let handler = GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor());
|
||||||
let mut out = String::new();
|
let mut out = String::new();
|
||||||
|
|
@ -206,3 +208,15 @@ fn test_serde_table(path: &str) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test_case("tests/data/concrete.vmt")]
|
||||||
|
#[test_case("tests/data/messy.vdf")]
|
||||||
|
#[test_case("tests/data/DialogConfigOverlay_1280x720.vdf")]
|
||||||
|
#[test_case("tests/data/serde_array_type.vdf")]
|
||||||
|
fn test_serde_from_table(path: &str) {
|
||||||
|
let raw = read_to_string(path).unwrap();
|
||||||
|
let result = Table::load_from_str(&raw).unwrap();
|
||||||
|
|
||||||
|
let material: Expected = from_entry(result.into()).expect("table to material");
|
||||||
|
insta::assert_ron_snapshot!(format!("table_to_material__{}", path), material);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,152 @@
|
||||||
|
---
|
||||||
|
source: tests/serde.rs
|
||||||
|
expression: material
|
||||||
|
---
|
||||||
|
UserConfigData(
|
||||||
|
Steam: UserConfigDataSteam(
|
||||||
|
cached: UserConfigDataSteamCached(
|
||||||
|
r#OverlaySplash.res: {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FriendsMainDialog: {
|
||||||
|
"xpos": 1028,
|
||||||
|
"ypos": 280,
|
||||||
|
"wide": 252,
|
||||||
|
"tall": 440,
|
||||||
|
"FriendPanelSelf": {},
|
||||||
|
"FriendsDialogSheet": UserConfigDataFriendsMainDialogFriendsDialogSheet(
|
||||||
|
FriendsFriendsPage: UserConfigDataFriendsMainDialogFriendsDialogSheetFriendsPage(
|
||||||
|
BuddyList: {
|
||||||
|
"0_collapsed": false,
|
||||||
|
"1_collapsed": false,
|
||||||
|
"2_collapsed": false,
|
||||||
|
"3_collapsed": false,
|
||||||
|
"4_collapsed": false,
|
||||||
|
"5_collapsed": false,
|
||||||
|
"allfriends_collapsed": false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
FriendsClansPage: UserConfigDataFriendsMainDialogFriendsDialogSheetFriendsPage(
|
||||||
|
BuddyList: {
|
||||||
|
"0_collapsed": false,
|
||||||
|
"1_collapsed": false,
|
||||||
|
"2_collapsed": false,
|
||||||
|
"3_collapsed": false,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
"FriendsState": {},
|
||||||
|
},
|
||||||
|
Servers: UserConfigDataServers(
|
||||||
|
r#DialogServerBrowser.res: {
|
||||||
|
"xpos": 0,
|
||||||
|
"ypos": 0,
|
||||||
|
"wide": 1280,
|
||||||
|
"tall": 720,
|
||||||
|
"GameTabs": UserConfigDataServersDialogGameTabs(
|
||||||
|
InternetGames: GameListHaver(
|
||||||
|
gamelist: GameList(
|
||||||
|
r##ServerBrowser_Password_hidden: false,
|
||||||
|
r##ServerBrowser_Bots_hidden: true,
|
||||||
|
r##ServerBrowser_Secure_hidden: false,
|
||||||
|
r##ServerBrowser_Servers_hidden: false,
|
||||||
|
r##ServerBrowser_IPAddress_hidden: true,
|
||||||
|
r##ServerBrowser_Game_hidden: false,
|
||||||
|
r##ServerBrowser_Players_hidden: false,
|
||||||
|
r##ServerBrowser_Map_hidden: false,
|
||||||
|
r##ServerBrowser_Latency_hidden: false,
|
||||||
|
sort_column: "#ServerBrowser_Latency",
|
||||||
|
sort_column_secondary: None,
|
||||||
|
sort_column_asc: true,
|
||||||
|
sort_column_secondary_asc: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FavoriteGames: GameListHaver(
|
||||||
|
gamelist: GameList(
|
||||||
|
r##ServerBrowser_Password_hidden: false,
|
||||||
|
r##ServerBrowser_Bots_hidden: true,
|
||||||
|
r##ServerBrowser_Secure_hidden: false,
|
||||||
|
r##ServerBrowser_Servers_hidden: false,
|
||||||
|
r##ServerBrowser_IPAddress_hidden: true,
|
||||||
|
r##ServerBrowser_Game_hidden: false,
|
||||||
|
r##ServerBrowser_Players_hidden: false,
|
||||||
|
r##ServerBrowser_Map_hidden: false,
|
||||||
|
r##ServerBrowser_Latency_hidden: false,
|
||||||
|
sort_column: "#ServerBrowser_Latency",
|
||||||
|
sort_column_secondary: None,
|
||||||
|
sort_column_asc: true,
|
||||||
|
sort_column_secondary_asc: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
HistoryGames: GameListHaver(
|
||||||
|
gamelist: GameList(
|
||||||
|
r##ServerBrowser_Password_hidden: false,
|
||||||
|
r##ServerBrowser_Bots_hidden: true,
|
||||||
|
r##ServerBrowser_Secure_hidden: false,
|
||||||
|
r##ServerBrowser_Servers_hidden: false,
|
||||||
|
r##ServerBrowser_IPAddress_hidden: true,
|
||||||
|
r##ServerBrowser_Game_hidden: false,
|
||||||
|
r##ServerBrowser_Players_hidden: false,
|
||||||
|
r##ServerBrowser_Map_hidden: false,
|
||||||
|
r##ServerBrowser_Latency_hidden: false,
|
||||||
|
sort_column: "#ServerBrowser_LastPlayed",
|
||||||
|
sort_column_secondary: Some("#ServerBrowser_Latency"),
|
||||||
|
sort_column_asc: true,
|
||||||
|
sort_column_secondary_asc: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SpectateGames: GameListHaver(
|
||||||
|
gamelist: GameList(
|
||||||
|
r##ServerBrowser_Password_hidden: false,
|
||||||
|
r##ServerBrowser_Bots_hidden: true,
|
||||||
|
r##ServerBrowser_Secure_hidden: false,
|
||||||
|
r##ServerBrowser_Servers_hidden: false,
|
||||||
|
r##ServerBrowser_IPAddress_hidden: true,
|
||||||
|
r##ServerBrowser_Game_hidden: false,
|
||||||
|
r##ServerBrowser_Players_hidden: false,
|
||||||
|
r##ServerBrowser_Map_hidden: false,
|
||||||
|
r##ServerBrowser_Latency_hidden: false,
|
||||||
|
sort_column: "#ServerBrowser_Latency",
|
||||||
|
sort_column_secondary: None,
|
||||||
|
sort_column_asc: true,
|
||||||
|
sort_column_secondary_asc: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
LanGames: GameListHaver(
|
||||||
|
gamelist: GameList(
|
||||||
|
r##ServerBrowser_Password_hidden: false,
|
||||||
|
r##ServerBrowser_Bots_hidden: true,
|
||||||
|
r##ServerBrowser_Secure_hidden: false,
|
||||||
|
r##ServerBrowser_Servers_hidden: false,
|
||||||
|
r##ServerBrowser_IPAddress_hidden: true,
|
||||||
|
r##ServerBrowser_Game_hidden: false,
|
||||||
|
r##ServerBrowser_Players_hidden: false,
|
||||||
|
r##ServerBrowser_Map_hidden: false,
|
||||||
|
r##ServerBrowser_Latency_hidden: false,
|
||||||
|
sort_column: "#ServerBrowser_Latency",
|
||||||
|
sort_column_secondary: None,
|
||||||
|
sort_column_asc: true,
|
||||||
|
sort_column_secondary_asc: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FriendsGames: GameListHaver(
|
||||||
|
gamelist: GameList(
|
||||||
|
r##ServerBrowser_Password_hidden: false,
|
||||||
|
r##ServerBrowser_Bots_hidden: true,
|
||||||
|
r##ServerBrowser_Secure_hidden: false,
|
||||||
|
r##ServerBrowser_Servers_hidden: false,
|
||||||
|
r##ServerBrowser_IPAddress_hidden: true,
|
||||||
|
r##ServerBrowser_Game_hidden: false,
|
||||||
|
r##ServerBrowser_Players_hidden: false,
|
||||||
|
r##ServerBrowser_Map_hidden: false,
|
||||||
|
r##ServerBrowser_Latency_hidden: false,
|
||||||
|
sort_column: "#ServerBrowser_Latency",
|
||||||
|
sort_column_secondary: None,
|
||||||
|
sort_column_asc: true,
|
||||||
|
sort_column_secondary_asc: true,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
---
|
||||||
|
source: tests/serde.rs
|
||||||
|
expression: material
|
||||||
|
---
|
||||||
|
LightmappedGeneric(
|
||||||
|
r#$baseTexture: "cp_mountainlab/concrete/concretefloor003",
|
||||||
|
r#$bumpmap: "concrete/concretefloor007b_height-ssbump",
|
||||||
|
r#$ssbump: true,
|
||||||
|
r#%keywords: "tf",
|
||||||
|
r#$detail: "overlays/detail001",
|
||||||
|
r#$detailscale: 1.9,
|
||||||
|
r#$detailblendmode: 0,
|
||||||
|
r#$detailblendfactor: 1.0,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
source: tests/serde.rs
|
||||||
|
expression: material
|
||||||
|
---
|
||||||
|
r#Resource/specificPanel.res(
|
||||||
|
empty: (),
|
||||||
|
array: [
|
||||||
|
1,
|
||||||
|
2,
|
||||||
|
3,
|
||||||
|
],
|
||||||
|
windows_path: "C:\\test\\no newline",
|
||||||
|
r#\\"$translucent": true,
|
||||||
|
r#$envmaptint: 0.5,
|
||||||
|
r#.5: 0.5,
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
---
|
||||||
|
source: tests/serde.rs
|
||||||
|
expression: material
|
||||||
|
---
|
||||||
|
Types(
|
||||||
|
fixed_array: (1, 2, 3),
|
||||||
|
flex_array: [
|
||||||
|
1.0,
|
||||||
|
2.2,
|
||||||
|
],
|
||||||
|
tuple: (true, 57),
|
||||||
|
single: 1.2,
|
||||||
|
triple: (1.2, 1.3, 1.4),
|
||||||
|
single_int: 2.0,
|
||||||
|
)
|
||||||
Loading…
Add table
Add a link
Reference in a new issue