1use malachite::base::{num::conversion::traits::RoundingFrom, rounding_modes::RoundingMode};
4use nickel_lang_parser::ast::InputFormat;
5use std::{ffi::OsString, io::Cursor, iter::ExactSizeIterator};
6
7use serde::de::{
8 Deserialize, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, SeqAccess,
9 VariantAccess, Visitor,
10};
11
12use crate::{
13 error::{self, NullReporter},
14 eval::{
15 cache::CacheImpl,
16 value::{
17 Array, ArrayData, Container, InlineValue, NickelValue, RecordData, ValueContent,
18 ValueContentRef,
19 },
20 },
21 identifier::LocIdent,
22 program::{Input, Program},
23 term::{IndexMap, record::Field},
24};
25
26macro_rules! deserialize_number {
27 ($method:ident, $type:tt, $visit:ident) => {
28 fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
29 where
30 V: Visitor<'de>,
31 {
32 match self.content_ref() {
33 ValueContentRef::Number(n) => {
34 return visitor.$visit($type::rounding_from(n, RoundingMode::Nearest).0);
35 }
36 _ => Err(RustDeserializationError::InvalidType {
37 expected: "Number".to_string(),
38 occurred: self.type_of().unwrap_or("Other").to_owned(),
39 }),
40 }
41 }
42 };
43}
44
45#[allow(clippy::large_enum_variant)]
47pub enum EvalOrDeserError {
48 Nickel {
49 error: error::Error,
50 files: Option<crate::files::Files>,
51 },
52 Deser(RustDeserializationError),
53}
54
55impl std::error::Error for EvalOrDeserError {}
56
57impl std::fmt::Debug for EvalOrDeserError {
58 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
59 match self {
60 Self::Nickel { error, files } => {
61 let filenames = files.as_ref().map(|f| f.filenames().collect::<Vec<_>>());
62 f.debug_struct("Nickel")
63 .field("error", error)
64 .field("files", &filenames)
65 .finish()
66 }
67 Self::Deser(arg0) => f.debug_tuple("Deser").field(arg0).finish(),
68 }
69 }
70}
71
72impl std::fmt::Display for EvalOrDeserError {
73 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74 match self {
75 EvalOrDeserError::Nickel { error, files } => {
76 let mut files = files.clone().unwrap_or_default();
77 write!(
78 f,
79 "{}",
80 crate::error::report::report_as_str(
81 &mut files,
82 error.clone(),
83 error::report::ColorOpt::Never
84 )
85 )
86 }
87 EvalOrDeserError::Deser(e) => e.fmt(f),
88 }
89 }
90}
91
92impl EvalOrDeserError {
93 fn new<E>(error: E, files: crate::files::Files) -> Self
94 where
95 E: Into<error::Error>,
96 {
97 Self::Nickel {
98 error: error.into(),
99 files: Some(files),
100 }
101 }
102}
103
104impl<E: Into<error::Error>> From<E> for EvalOrDeserError {
105 fn from(err: E) -> Self {
106 Self::Nickel {
107 error: err.into(),
108 files: None,
109 }
110 }
111}
112
113impl From<RustDeserializationError> for EvalOrDeserError {
114 fn from(err: RustDeserializationError) -> Self {
115 Self::Deser(err)
116 }
117}
118
119fn from_input<'a, T, Content, Source>(input: Input<Content, Source>) -> Result<T, EvalOrDeserError>
120where
121 T: serde::Deserialize<'a>,
122 Content: std::io::Read,
123 Source: Into<OsString>,
124{
125 let mut program =
126 Program::<CacheImpl>::new_from_input(input, std::io::stderr(), NullReporter {})
127 .map_err(error::IOError::from)?;
128
129 Ok(T::deserialize(program.eval_full_for_export().map_err(
130 |err| EvalOrDeserError::new(err, program.files()),
131 )?)?)
132}
133
134pub fn from_str<'a, T>(s: &'a str) -> Result<T, EvalOrDeserError>
135where
136 T: serde::Deserialize<'a>,
137{
138 from_input(Input::Source(Cursor::new(s), "string", InputFormat::Nickel))
139}
140
141pub fn from_slice<'a, T>(v: &'a [u8]) -> Result<T, EvalOrDeserError>
142where
143 T: serde::Deserialize<'a>,
144{
145 from_input(Input::Source(Cursor::new(v), "slice", InputFormat::Nickel))
146}
147
148pub fn from_path<T>(path: impl Into<OsString>) -> Result<T, EvalOrDeserError>
149where
150 T: serde::de::DeserializeOwned,
151{
152 from_input(Input::<std::fs::File, _>::Path(path))
153}
154
155pub fn from_reader<R, T>(rdr: R) -> Result<T, EvalOrDeserError>
156where
157 R: std::io::Read,
158 T: serde::de::DeserializeOwned,
159{
160 from_input(Input::Source(rdr, "reader", InputFormat::Nickel))
161}
162
163#[derive(Debug, PartialEq, Eq, Clone)]
165pub enum RustDeserializationError {
166 InvalidType { expected: String, occurred: String },
167 MissingValue,
168 EmptyRecordField,
169 UnimplementedType { occurred: String },
170 InvalidRecordLength(usize),
171 InvalidArrayLength(usize),
172 Other(String),
173}
174
175impl<'de> serde::Deserializer<'de> for NickelValue {
176 type Error = RustDeserializationError;
177
178 fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
180 where
181 V: Visitor<'de>,
182 {
183 match self.content() {
184 ValueContent::Null(_) => visitor.visit_unit(),
185 ValueContent::Bool(lens) => visitor.visit_bool(lens.take()),
186 ValueContent::Number(lens) => {
187 visitor.visit_f64(f64::rounding_from(lens.take(), RoundingMode::Nearest).0)
188 }
189 ValueContent::String(lens) => visitor.visit_string(lens.take().into_inner()),
190 ValueContent::EnumVariant(lens) => {
191 let enum_variant = lens.take();
192
193 visitor.visit_enum(EnumDeserializer {
194 tag: enum_variant.tag.into_label(),
195 value: enum_variant.arg,
196 })
197 }
198 ValueContent::Record(lens) => visit_record_container(lens.take(), visitor),
199 ValueContent::Array(lens) => visit_array_container(lens.take(), visitor),
200 lens => Err(RustDeserializationError::UnimplementedType {
201 occurred: lens.restore().type_of().unwrap_or("Other").to_owned(),
202 }),
203 }
204 }
205
206 deserialize_number!(deserialize_i8, i8, visit_i8);
207 deserialize_number!(deserialize_i16, i16, visit_i16);
208 deserialize_number!(deserialize_i32, i32, visit_i32);
209 deserialize_number!(deserialize_i64, i64, visit_i64);
210 deserialize_number!(deserialize_i128, i128, visit_i128);
211 deserialize_number!(deserialize_u8, u8, visit_u8);
212 deserialize_number!(deserialize_u16, u16, visit_u16);
213 deserialize_number!(deserialize_u32, u32, visit_u32);
214 deserialize_number!(deserialize_u64, u64, visit_u64);
215 deserialize_number!(deserialize_u128, u128, visit_u128);
216 deserialize_number!(deserialize_f32, f32, visit_f32);
217 deserialize_number!(deserialize_f64, f64, visit_f64);
218
219 fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
221 where
222 V: Visitor<'de>,
223 {
224 if self.is_null() {
225 visitor.visit_none()
226 } else {
227 visitor.visit_some(self)
228 }
229 }
230
231 fn deserialize_enum<V>(
233 self,
234 _name: &str,
235 _variants: &'static [&'static str],
236 visitor: V,
237 ) -> Result<V::Value, Self::Error>
238 where
239 V: Visitor<'de>,
240 {
241 let (tag, arg) = match self.content() {
242 ValueContent::EnumVariant(lens) => {
243 let enum_var = lens.take();
244
245 (enum_var.tag.into_label(), enum_var.arg)
246 }
247 ValueContent::Record(lens) => {
248 let record = lens.take().unwrap_or_alloc();
249
250 let mut iter = record.fields.into_iter();
251 let (tag, arg) = match iter.next() {
252 Some((id, Field { value, .. })) => (id, value),
253 None => {
254 return Err(RustDeserializationError::InvalidType {
255 expected: "Record with single key".to_string(),
256 occurred: "Record without keys".to_string(),
257 });
258 }
259 };
260
261 if iter.next().is_some() {
262 return Err(RustDeserializationError::InvalidType {
263 expected: "Record with single key".to_string(),
264 occurred: "Record with multiple keys".to_string(),
265 });
266 }
267
268 (tag.into_label(), arg)
269 }
270 lens => {
271 let value = lens.restore();
272
273 return Err(RustDeserializationError::InvalidType {
274 expected: "Enum or Record".to_string(),
275 occurred: value.type_of().unwrap_or("Other").to_owned(),
276 });
277 }
278 };
279
280 visitor.visit_enum(EnumDeserializer { tag, value: arg })
281 }
282
283 fn deserialize_newtype_struct<V>(
285 self,
286 _name: &'static str,
287 visitor: V,
288 ) -> Result<V::Value, Self::Error>
289 where
290 V: Visitor<'de>,
291 {
292 visitor.visit_newtype_struct(self)
293 }
294
295 fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
297 where
298 V: Visitor<'de>,
299 {
300 match self.as_inline() {
301 Some(InlineValue::True) => visitor.visit_bool(true),
302 Some(InlineValue::False) => visitor.visit_bool(false),
303 _ => Err(RustDeserializationError::InvalidType {
304 expected: "Bool".to_string(),
305 occurred: self.type_of().unwrap_or("Other").to_owned(),
306 }),
307 }
308 }
309
310 fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
312 where
313 V: Visitor<'de>,
314 {
315 self.deserialize_string(visitor)
316 }
317
318 fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
320 where
321 V: Visitor<'de>,
322 {
323 match self.as_string() {
324 Some(s) => visitor.visit_str(s),
325 _ => Err(RustDeserializationError::InvalidType {
326 expected: "String".to_string(),
327 occurred: self.type_of().unwrap_or("Other").to_owned(),
328 }),
329 }
330 }
331
332 fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
334 where
335 V: Visitor<'de>,
336 {
337 match self.content() {
338 ValueContent::String(lens) => visitor.visit_string(lens.take().into_inner()),
339 lens => Err(RustDeserializationError::InvalidType {
340 expected: "String".to_string(),
341 occurred: lens.restore().type_of().unwrap_or("Other").to_owned(),
342 }),
343 }
344 }
345
346 fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
348 where
349 V: Visitor<'de>,
350 {
351 self.deserialize_byte_buf(visitor)
352 }
353
354 fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
356 where
357 V: Visitor<'de>,
358 {
359 match self.content() {
360 ValueContent::String(lens) => visitor.visit_string(lens.take().into_inner()),
361 ValueContent::Array(lens) => visit_array(lens.take().unwrap_or_alloc().array, visitor),
362 lens => {
363 let value = lens.restore();
364
365 Err(RustDeserializationError::InvalidType {
366 expected: "Str or Array".to_string(),
367 occurred: value.type_of().unwrap_or("Other").to_owned(),
368 })
369 }
370 }
371 }
372
373 fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
375 where
376 V: Visitor<'de>,
377 {
378 match self.as_inline() {
379 Some(InlineValue::Null) => visitor.visit_unit(),
380 _ => Err(RustDeserializationError::InvalidType {
381 expected: "Null".to_string(),
382 occurred: self.type_of().unwrap_or("Other").to_owned(),
383 }),
384 }
385 }
386
387 fn deserialize_unit_struct<V>(
389 self,
390 _name: &'static str,
391 visitor: V,
392 ) -> Result<V::Value, Self::Error>
393 where
394 V: Visitor<'de>,
395 {
396 self.deserialize_unit(visitor)
397 }
398
399 fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
401 where
402 V: Visitor<'de>,
403 {
404 match self.content() {
405 ValueContent::Array(lens) => visit_array_container(lens.take(), visitor),
406 lens => Err(RustDeserializationError::InvalidType {
407 expected: "Array".to_string(),
408 occurred: lens.restore().type_of().unwrap_or("Other").to_owned(),
409 }),
410 }
411 }
412
413 fn deserialize_tuple<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
415 where
416 V: Visitor<'de>,
417 {
418 self.deserialize_seq(visitor)
419 }
420
421 fn deserialize_tuple_struct<V>(
423 self,
424 _name: &'static str,
425 _len: usize,
426 visitor: V,
427 ) -> Result<V::Value, Self::Error>
428 where
429 V: Visitor<'de>,
430 {
431 self.deserialize_seq(visitor)
432 }
433
434 fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
436 where
437 V: Visitor<'de>,
438 {
439 match self.content() {
440 ValueContent::Record(lens) => visit_record_container(lens.take(), visitor),
441 lens => Err(RustDeserializationError::InvalidType {
442 expected: "Record".to_string(),
443 occurred: lens.restore().type_of().unwrap_or("Other").to_owned(),
444 }),
445 }
446 }
447
448 fn deserialize_struct<V>(
450 self,
451 _name: &'static str,
452 _fields: &'static [&'static str],
453 visitor: V,
454 ) -> Result<V::Value, Self::Error>
455 where
456 V: Visitor<'de>,
457 {
458 match self.content() {
459 ValueContent::Array(lens) => visit_array_container(lens.take(), visitor),
460 ValueContent::Record(lens) => visit_record_container(lens.take(), visitor),
461 lens => {
462 let value = lens.restore();
463
464 Err(RustDeserializationError::InvalidType {
465 expected: "Record".to_string(),
466 occurred: value.type_of().unwrap_or("Other").to_owned(),
467 })
468 }
469 }
470 }
471
472 fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
474 where
475 V: Visitor<'de>,
476 {
477 self.deserialize_string(visitor)
478 }
479
480 fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
481 where
482 V: Visitor<'de>,
483 {
484 drop(self);
485 visitor.visit_unit()
486 }
487}
488
489struct ArrayDeserializer {
490 iter: <Array as IntoIterator>::IntoIter,
491}
492
493impl ArrayDeserializer {
494 fn new(array: Array) -> Self {
495 ArrayDeserializer {
496 iter: array.into_iter(),
497 }
498 }
499}
500
501impl<'de> SeqAccess<'de> for ArrayDeserializer {
502 type Error = RustDeserializationError;
503
504 fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
505 where
506 T: DeserializeSeed<'de>,
507 {
508 match self.iter.next() {
509 Some(value) => seed.deserialize(value).map(Some),
510 None => Ok(None),
511 }
512 }
513
514 fn size_hint(&self) -> Option<usize> {
515 match self.iter.size_hint() {
516 (lower, Some(upper)) if lower == upper => Some(upper),
517 _ => None,
518 }
519 }
520}
521
522fn visit_array_container<'de, V>(
523 container: Container<ArrayData>,
524 visitor: V,
525) -> Result<V::Value, RustDeserializationError>
526where
527 V: Visitor<'de>,
528{
529 visit_array(container.unwrap_or_alloc().array, visitor)
530}
531
532fn visit_array<'de, V>(array: Array, visitor: V) -> Result<V::Value, RustDeserializationError>
533where
534 V: Visitor<'de>,
535{
536 let len = array.len();
537 let mut deserializer = ArrayDeserializer::new(array);
538 let seq = visitor.visit_seq(&mut deserializer)?;
539 if deserializer.iter.next().is_none() {
540 Ok(seq)
541 } else {
542 Err(RustDeserializationError::InvalidArrayLength(len))
543 }
544}
545
546struct RecordDeserializer {
547 iter: <IndexMap<LocIdent, Field> as IntoIterator>::IntoIter,
548 field: Option<Field>,
549}
550
551impl RecordDeserializer {
552 fn new(map: IndexMap<LocIdent, Field>) -> Self {
553 RecordDeserializer {
554 iter: map.into_iter(),
555 field: None,
556 }
557 }
558}
559
560impl<'de> MapAccess<'de> for RecordDeserializer {
561 type Error = RustDeserializationError;
562
563 fn next_key_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error>
564 where
565 T: DeserializeSeed<'de>,
566 {
567 match self.iter.next() {
568 Some((key, value)) => {
569 self.field = Some(value);
570 seed.deserialize(key.label().into_deserializer()).map(Some)
571 }
572 None => Ok(None),
573 }
574 }
575
576 fn next_value_seed<T>(&mut self, seed: T) -> Result<T::Value, Self::Error>
577 where
578 T: DeserializeSeed<'de>,
579 {
580 match self.field.take() {
581 Some(Field {
582 value: Some(value), ..
583 }) => seed.deserialize(value),
584 Some(Field { value: None, .. }) => Err(RustDeserializationError::EmptyRecordField),
591 _ => Err(RustDeserializationError::MissingValue),
592 }
593 }
594
595 fn size_hint(&self) -> Option<usize> {
596 match self.iter.size_hint() {
597 (lower, Some(upper)) if lower == upper => Some(upper),
598 _ => None,
599 }
600 }
601}
602
603fn visit_record_container<'de, V>(
604 container: Container<RecordData>,
605 visitor: V,
606) -> Result<V::Value, RustDeserializationError>
607where
608 V: Visitor<'de>,
609{
610 visit_record(container.unwrap_or_alloc().fields, visitor)
611}
612
613fn visit_record<'de, V>(
614 record: IndexMap<LocIdent, Field>,
615 visitor: V,
616) -> Result<V::Value, RustDeserializationError>
617where
618 V: Visitor<'de>,
619{
620 let len = record.len();
621 let mut deserializer = RecordDeserializer::new(record);
622 let map = visitor.visit_map(&mut deserializer)?;
623 let remaining = deserializer.iter.len();
624 if remaining == 0 {
625 Ok(map)
626 } else {
627 Err(RustDeserializationError::InvalidRecordLength(len))
628 }
629}
630
631struct VariantDeserializer {
632 value: Option<NickelValue>,
633}
634
635impl<'de> VariantAccess<'de> for VariantDeserializer {
636 type Error = RustDeserializationError;
637
638 fn unit_variant(self) -> Result<(), Self::Error> {
639 match self.value {
640 Some(value) => Deserialize::deserialize(value),
641 None => Ok(()),
642 }
643 }
644
645 fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Self::Error>
646 where
647 T: DeserializeSeed<'de>,
648 {
649 match self.value {
650 Some(value) => seed.deserialize(value),
651 None => Err(RustDeserializationError::MissingValue),
652 }
653 }
654
655 fn tuple_variant<V>(self, _len: usize, visitor: V) -> Result<V::Value, Self::Error>
656 where
657 V: Visitor<'de>,
658 {
659 match self.value.map(|v| v.content()) {
660 Some(ValueContent::Array(lens)) => {
661 let v = lens.take().unwrap_or_alloc().array;
662
663 if v.is_empty() {
664 visitor.visit_unit()
665 } else {
666 visit_array(v, visitor)
667 }
668 }
669 Some(lens) => Err(RustDeserializationError::InvalidType {
670 expected: "Array variant".to_string(),
671 occurred: lens.restore().type_of().unwrap_or("Other").to_owned(),
672 }),
673 None => Err(RustDeserializationError::MissingValue),
674 }
675 }
676
677 fn struct_variant<V>(
678 self,
679 _fields: &'static [&'static str],
680 visitor: V,
681 ) -> Result<V::Value, Self::Error>
682 where
683 V: Visitor<'de>,
684 {
685 match self.value.map(|v| v.content()) {
686 Some(ValueContent::Record(lens)) => visit_record_container(lens.take(), visitor),
687 Some(lens) => Err(RustDeserializationError::InvalidType {
688 expected: "Array variant".to_string(),
689 occurred: lens.restore().type_of().unwrap_or("Other").to_owned(),
690 }),
691 None => Err(RustDeserializationError::MissingValue),
692 }
693 }
694}
695
696struct EnumDeserializer {
697 tag: String,
698 value: Option<NickelValue>,
699}
700
701impl<'de> EnumAccess<'de> for EnumDeserializer {
702 type Error = RustDeserializationError;
703 type Variant = VariantDeserializer;
704
705 fn variant_seed<V>(self, seed: V) -> Result<(V::Value, VariantDeserializer), Self::Error>
706 where
707 V: DeserializeSeed<'de>,
708 {
709 let variant = self.tag.into_deserializer();
710 let visitor = VariantDeserializer { value: self.value };
711 seed.deserialize(variant).map(|v| (v, visitor))
712 }
713}
714
715impl std::fmt::Display for RustDeserializationError {
716 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
717 match self {
718 RustDeserializationError::InvalidType { expected, occurred } => {
719 write!(f, "invalid type: {occurred}, expected: {expected}")
720 }
721 RustDeserializationError::MissingValue => write!(f, "missing value"),
722 RustDeserializationError::EmptyRecordField => write!(f, "empty Metavalue"),
723 RustDeserializationError::InvalidRecordLength(len) => {
724 write!(f, "invalid record length, expected {len}")
725 }
726 RustDeserializationError::InvalidArrayLength(len) => {
727 write!(f, "invalid array length, expected {len}")
728 }
729 RustDeserializationError::UnimplementedType { occurred } => {
730 write!(f, "unimplemented conversion from type: {occurred}")
731 }
732 RustDeserializationError::Other(err) => write!(f, "{err}"),
733 }
734 }
735}
736
737impl std::error::Error for RustDeserializationError {}
738
739impl serde::de::Error for RustDeserializationError {
740 fn custom<T>(msg: T) -> Self
741 where
742 T: std::fmt::Display,
743 {
744 RustDeserializationError::Other(msg.to_string())
745 }
746}
747
748#[cfg(test)]
749mod tests {
750 use super::{from_path, from_reader, from_slice, from_str};
751 use std::io::Cursor;
752
753 use nickel_lang_utils::{
754 nickel_lang_core::{
755 deserialize::RustDeserializationError, error::NullReporter, eval::value::NickelValue,
756 },
757 test_program::TestProgram,
758 };
759 use serde::Deserialize;
760
761 fn eval(source: &str) -> NickelValue {
762 TestProgram::new_from_source(
763 Cursor::new(source),
764 "source",
765 std::io::stderr(),
766 NullReporter {},
767 )
768 .expect("program shouldn't fail")
769 .eval_full()
770 .expect("evaluation shouldn't fail")
771 }
772
773 #[test]
774 fn rust_deserialize_struct_with_fields() {
775 #[derive(Debug, PartialEq, Deserialize)]
776 #[serde(rename_all = "lowercase")]
777 enum E {
778 Foo,
779 Bar,
780 }
781
782 #[derive(Debug, PartialEq, Deserialize)]
783 #[serde(rename_all = "lowercase")]
784 enum H {
785 Foo(u16),
786 Bar(String),
787 }
788
789 #[derive(Debug, PartialEq, Deserialize)]
790 struct A {
791 a: f64,
792 b: String,
793 c: (),
794 d: bool,
795 e: E,
796 f: Option<bool>,
797 g: i16,
798 h: H,
799 }
800
801 assert_eq!(
802 A::deserialize(eval(
803 r#"{ a = 10, b = "test string", c = null, d = true, e = 'foo, f = null,
804 g = -10, h = { bar = "some other string" } }"#
805 ))
806 .expect("deserialization shouldn't fail"),
807 A {
808 a: 10.0,
809 b: "test string".to_string(),
810 c: (),
811 d: true,
812 e: E::Foo,
813 f: None,
814 g: -10,
815 h: H::Bar("some other string".to_string())
816 }
817 )
818 }
819
820 #[test]
821 fn rust_deserialize_array_of_numbers() {
822 assert_eq!(
823 Vec::<f64>::deserialize(eval(r#"[1, 2, 3, 4]"#))
824 .expect("deserialization shouldn't fail"),
825 vec![1.0, 2.0, 3.0, 4.0]
826 )
827 }
828
829 #[test]
830 fn rust_deserialize_fail_non_data() {
831 #[derive(Debug, PartialEq, Deserialize)]
832 struct A;
833
834 assert_eq!(
835 A::deserialize(eval(r#"fun a b => a + b"#)),
836 Err(RustDeserializationError::InvalidType {
837 expected: "Null".to_string(),
838 occurred: "Function".to_string()
839 })
840 )
841 }
842
843 #[test]
844 fn rust_deserialize_ignore_annotation() {
845 #[derive(Debug, PartialEq, Deserialize)]
846 struct A {
847 a: f64,
848 }
849
850 assert_eq!(
851 A::deserialize(eval(r#"{ a = (10 | Number) }"#))
852 .expect("deserialization shouldn't fail"),
853 A { a: 10.0 }
854 )
855 }
856
857 #[test]
858 fn rust_deserialize_wrappers() {
859 #[derive(Debug, Clone, PartialEq, Deserialize)]
860 struct A {
861 a: f64,
862 b: Vec<String>,
863 }
864
865 let a = A {
866 a: 10.0,
867 b: vec!["a".into(), "b".into()],
868 };
869
870 assert_eq!(
871 from_str::<A>(r#"{ a = (10 | Number), b = ["a", "b"] }"#).unwrap(),
872 a.clone()
873 );
874
875 assert_eq!(
876 from_slice::<A>(br#"{ a = (10 | Number), b = ["a", "b"] }"#).unwrap(),
877 a.clone()
878 );
879
880 assert_eq!(
881 from_reader::<_, A>(Cursor::new(r#"{ a = (10 | Number), b = ["a", "b"] }"#)).unwrap(),
882 a.clone()
883 );
884
885 assert_eq!(
886 from_reader::<_, A>(Cursor::new(br#"{ a = (10 | Number), b = ["a", "b"] }"#)).unwrap(),
887 a.clone()
888 );
889
890 assert_eq!(
891 from_path::<f64>(
892 nickel_lang_utils::project_root::project_root()
893 .join("examples/fibonacci/fibonacci.ncl")
894 )
895 .unwrap(),
896 55.0
897 );
898
899 assert!(from_str::<String>("will not parse").is_err());
900 assert!(from_str::<String>("1 | String").is_err());
901 }
902}