1use crate::{
2 NuGlob, Range, Record, ShellError, Span, Spanned, Type, Value,
3 ast::{CellPath, PathMember},
4 casing::Casing,
5 engine::Closure,
6 shell_error::generic::GenericError,
7};
8use chrono::{DateTime, FixedOffset};
9use std::{
10 any,
11 borrow::Cow,
12 cmp::Ordering,
13 collections::{HashMap, VecDeque},
14 ffi::OsString,
15 fmt,
16 num::{
17 NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroIsize, NonZeroU16, NonZeroU32,
18 NonZeroU64, NonZeroUsize,
19 },
20 path::PathBuf,
21 str::FromStr,
22};
23
24pub trait FromValue: Sized {
125 fn from_value(v: Value) -> Result<Self, ShellError>;
131
132 fn expected_type() -> Type {
143 Type::Custom(
144 any::type_name::<Self>()
145 .split(':')
146 .next_back()
147 .expect("str::split returns an iterator with at least one element")
148 .to_string()
149 .into_boxed_str(),
150 )
151 }
152}
153
154impl<T, const N: usize> FromValue for [T; N]
157where
158 T: FromValue,
159{
160 fn from_value(v: Value) -> Result<Self, ShellError> {
161 let span = v.span();
162 let v_ty = v.get_type();
163 let vec = Vec::<T>::from_value(v)?;
164 vec.try_into()
165 .map_err(|err_vec: Vec<T>| ShellError::CantConvert {
166 to_type: Self::expected_type().to_string(),
167 from_type: v_ty.to_string(),
168 span,
169 help: Some(match err_vec.len().cmp(&N) {
170 Ordering::Less => format!(
171 "input list too short ({}), expected length of {N}, add missing values",
172 err_vec.len()
173 ),
174 Ordering::Equal => {
175 unreachable!("conversion would have worked if the length would be the same")
176 }
177 Ordering::Greater => format!(
178 "input list too long ({}), expected length of {N}, remove trailing values",
179 err_vec.len()
180 ),
181 }),
182 })
183 }
184
185 fn expected_type() -> Type {
186 Type::Custom(format!("list<{};{N}>", T::expected_type()).into_boxed_str())
187 }
188}
189
190impl FromValue for bool {
191 fn from_value(v: Value) -> Result<Self, ShellError> {
192 match v {
193 Value::Bool { val, .. } => Ok(val),
194 v => Err(ShellError::CantConvert {
195 to_type: Self::expected_type().to_string(),
196 from_type: v.get_type().to_string(),
197 span: v.span(),
198 help: None,
199 }),
200 }
201 }
202
203 fn expected_type() -> Type {
204 Type::Bool
205 }
206}
207
208impl FromValue for char {
209 fn from_value(v: Value) -> Result<Self, ShellError> {
210 let span = v.span();
211 let v_ty = v.get_type();
212 match v {
213 Value::String { ref val, .. } => match char::from_str(val) {
214 Ok(c) => Ok(c),
215 Err(_) => Err(ShellError::CantConvert {
216 to_type: Self::expected_type().to_string(),
217 from_type: v_ty.to_string(),
218 span,
219 help: Some("make the string only one char long".to_string()),
220 }),
221 },
222 _ => Err(ShellError::CantConvert {
223 to_type: Self::expected_type().to_string(),
224 from_type: v_ty.to_string(),
225 span,
226 help: None,
227 }),
228 }
229 }
230
231 fn expected_type() -> Type {
232 Type::String
233 }
234}
235
236impl FromValue for f32 {
237 fn from_value(v: Value) -> Result<Self, ShellError> {
238 f64::from_value(v).map(|float| float as f32)
239 }
240}
241
242impl FromValue for f64 {
243 fn from_value(v: Value) -> Result<Self, ShellError> {
244 match v {
245 Value::Float { val, .. } => Ok(val),
246 Value::Int { val, .. } => Ok(val as f64),
247 v => Err(ShellError::CantConvert {
248 to_type: Self::expected_type().to_string(),
249 from_type: v.get_type().to_string(),
250 span: v.span(),
251 help: None,
252 }),
253 }
254 }
255
256 fn expected_type() -> Type {
257 Type::Float
258 }
259}
260
261impl FromValue for i64 {
262 fn from_value(v: Value) -> Result<Self, ShellError> {
263 match v {
264 Value::Int { val, .. } => Ok(val),
265 Value::Duration { val, .. } => Ok(val),
266 v => Err(ShellError::CantConvert {
267 to_type: Self::expected_type().to_string(),
268 from_type: v.get_type().to_string(),
269 span: v.span(),
270 help: None,
271 }),
272 }
273 }
274
275 fn expected_type() -> Type {
276 Type::Int
277 }
278}
279
280impl FromValue for std::time::Duration {
282 fn from_value(v: Value) -> Result<Self, ShellError> {
283 match v {
284 Value::Duration { val, .. } => {
285 let nanos = u64::try_from(val)
286 .map_err(|_| ShellError::NeedsPositiveValue { span: v.span() })?;
287 Ok(Self::from_nanos(nanos))
288 }
289 v => Err(ShellError::CantConvert {
290 to_type: Self::expected_type().to_string(),
291 from_type: v.get_type().to_string(),
292 span: v.span(),
293 help: None,
294 }),
295 }
296 }
297
298 fn expected_type() -> Type {
299 Type::Duration
300 }
301}
302
303macro_rules! impl_from_value_for_nonzero {
309 ($nonzero:ty, $base:ty) => {
310 impl FromValue for $nonzero {
311 fn from_value(v: Value) -> Result<Self, ShellError> {
312 let span = v.span();
313 let val = <$base>::from_value(v)?;
314 <$nonzero>::new(val).ok_or_else(|| ShellError::IncorrectValue {
315 msg: "use a value other than 0".into(),
316 val_span: span,
317 call_span: span,
318 })
319 }
320
321 fn expected_type() -> Type {
322 Type::Int
323 }
324 }
325 };
326}
327
328impl_from_value_for_nonzero!(NonZeroU16, u16);
329impl_from_value_for_nonzero!(NonZeroU32, u32);
330impl_from_value_for_nonzero!(NonZeroU64, u64);
331impl_from_value_for_nonzero!(NonZeroUsize, usize);
332
333impl_from_value_for_nonzero!(NonZeroI8, i8);
334impl_from_value_for_nonzero!(NonZeroI16, i16);
335impl_from_value_for_nonzero!(NonZeroI32, i32);
336impl_from_value_for_nonzero!(NonZeroI64, i64);
337impl_from_value_for_nonzero!(NonZeroIsize, isize);
338
339macro_rules! impl_from_value_for_int {
340 ($type:ty) => {
341 impl FromValue for $type {
342 fn from_value(v: Value) -> Result<Self, ShellError> {
343 let span = v.span();
344 let int = i64::from_value(v)?;
345 const MIN: i64 = <$type>::MIN as i64;
346 const MAX: i64 = <$type>::MAX as i64;
347 #[allow(overlapping_range_endpoints)] #[allow(unreachable_patterns)] <$type>::try_from(int).map_err(|_| match int {
350 MIN..=MAX => unreachable!(
351 "int should be within the valid range for {}",
352 stringify!($type)
353 ),
354 i64::MIN..=MIN => int_too_small_error(int, <$type>::MIN, span),
355 MAX..=i64::MAX => int_too_large_error(int, <$type>::MAX, span),
356 })
357 }
358
359 fn expected_type() -> Type {
360 i64::expected_type()
361 }
362 }
363 };
364}
365
366impl_from_value_for_int!(i8);
367impl_from_value_for_int!(i16);
368impl_from_value_for_int!(i32);
369impl_from_value_for_int!(isize);
370
371macro_rules! impl_from_value_for_uint {
372 ($type:ty, $max:expr) => {
373 impl FromValue for $type {
374 fn from_value(v: Value) -> Result<Self, ShellError> {
375 let span = v.span();
376 const MAX: i64 = $max;
377 match v {
378 Value::Int { val, .. } | Value::Duration { val, .. } => {
379 match val {
380 i64::MIN..=-1 => Err(ShellError::NeedsPositiveValue { span }),
381 0..=MAX => Ok(val as $type),
382 #[allow(unreachable_patterns)] n => Err(ShellError::Generic(GenericError::new(
384 "Integer too large",
385 format!("{n} is larger than {MAX}"),
386 span,
387 ))),
388 }
389 }
390 v => Err(ShellError::CantConvert {
391 to_type: Self::expected_type().to_string(),
392 from_type: v.get_type().to_string(),
393 span: v.span(),
394 help: None,
395 }),
396 }
397 }
398
399 fn expected_type() -> Type {
400 Type::Custom("non-negative int".to_string().into_boxed_str())
401 }
402 }
403 };
404}
405
406impl_from_value_for_uint!(u16, u16::MAX as i64);
413impl_from_value_for_uint!(u32, u32::MAX as i64);
414impl_from_value_for_uint!(u64, i64::MAX); #[cfg(target_pointer_width = "64")]
416impl_from_value_for_uint!(usize, i64::MAX);
417#[cfg(target_pointer_width = "32")]
418impl_from_value_for_uint!(usize, usize::MAX as i64);
419
420impl FromValue for () {
421 fn from_value(v: Value) -> Result<Self, ShellError> {
422 match v {
423 Value::Nothing { .. } => Ok(()),
424 v => Err(ShellError::CantConvert {
425 to_type: Self::expected_type().to_string(),
426 from_type: v.get_type().to_string(),
427 span: v.span(),
428 help: None,
429 }),
430 }
431 }
432
433 fn expected_type() -> Type {
434 Type::Nothing
435 }
436}
437
438macro_rules! tuple_from_value {
439 ($template:literal, $($t:ident:$n:tt),+) => {
440 impl<$($t),+> FromValue for ($($t,)+) where $($t: FromValue,)+ {
441 fn from_value(v: Value) -> Result<Self, ShellError> {
442 let span = v.span();
443 match v {
444 Value::List { vals, .. } => {
445 let mut deque = VecDeque::from(vals);
446
447 Ok(($(
448 {
449 let v = deque.pop_front().ok_or_else(|| ShellError::CantFindColumn {
450 col_name: $n.to_string(),
451 span: None,
452 src_span: span
453 })?;
454 $t::from_value(v)?
455 },
456 )*))
457 },
458 v => Err(ShellError::CantConvert {
459 to_type: Self::expected_type().to_string(),
460 from_type: v.get_type().to_string(),
461 span: v.span(),
462 help: None,
463 }),
464 }
465 }
466
467 fn expected_type() -> Type {
468 Type::Custom(
469 format!(
470 $template,
471 $($t::expected_type()),*
472 )
473 .into_boxed_str(),
474 )
475 }
476 }
477 };
478}
479
480tuple_from_value!("[{}]", T0:0);
482tuple_from_value!("[{}, {}]", T0:0, T1:1);
483tuple_from_value!("[{}, {}, {}]", T0:0, T1:1, T2:2);
484tuple_from_value!("[{}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3);
485tuple_from_value!("[{}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4);
486tuple_from_value!("[{}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5);
487tuple_from_value!("[{}, {}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6);
488tuple_from_value!("[{}, {}, {}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7);
489tuple_from_value!("[{}, {}, {}, {}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8);
490tuple_from_value!("[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9);
491tuple_from_value!("[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10);
492tuple_from_value!("[{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}]", T0:0, T1:1, T2:2, T3:3, T4:4, T5:5, T6:6, T7:7, T8:8, T9:9, T10:10, T11:11);
493
494impl FromValue for PathBuf {
497 fn from_value(v: Value) -> Result<Self, ShellError> {
498 match v {
499 Value::String { val, .. } => Ok(val.into()),
500 v => Err(ShellError::CantConvert {
501 to_type: Self::expected_type().to_string(),
502 from_type: v.get_type().to_string(),
503 span: v.span(),
504 help: None,
505 }),
506 }
507 }
508
509 fn expected_type() -> Type {
510 Type::String
511 }
512}
513
514impl FromValue for OsString {
516 fn from_value(v: Value) -> Result<Self, ShellError> {
517 match v {
518 Value::String { val, .. } => Ok(OsString::from(val)),
519 Value::CellPath { val, .. } => Ok(OsString::from(val.to_string())),
520 v => Err(ShellError::CantConvert {
521 to_type: Self::expected_type().to_string(),
522 from_type: v.get_type().to_string(),
523 span: v.span(),
524 help: None,
525 }),
526 }
527 }
528
529 fn expected_type() -> Type {
530 Type::String
532 }
533}
534
535impl FromValue for String {
536 fn from_value(v: Value) -> Result<Self, ShellError> {
537 match v {
539 Value::CellPath { val, .. } => Ok(val.to_string()),
540 Value::String { val, .. } => Ok(val),
541 v => Err(ShellError::CantConvert {
542 to_type: Self::expected_type().to_string(),
543 from_type: v.get_type().to_string(),
544 span: v.span(),
545 help: None,
546 }),
547 }
548 }
549
550 fn expected_type() -> Type {
551 Type::String
552 }
553}
554
555impl FromValue for Vec<u8> {
558 fn from_value(v: Value) -> Result<Self, ShellError> {
559 match v {
560 Value::Binary { val, .. } => Ok(val),
561 Value::String { val, .. } => Ok(val.into_bytes()),
562 Value::List { vals, .. } => {
563 const U8MIN: i64 = u8::MIN as i64;
564 const U8MAX: i64 = u8::MAX as i64;
565 let mut this = Vec::with_capacity(vals.len());
566 for val in vals {
567 let span = val.span();
568 let int = i64::from_value(val)?;
569 #[allow(overlapping_range_endpoints)]
571 #[allow(clippy::match_overlapping_arm)]
572 match int {
573 U8MIN..=U8MAX => this.push(int as u8),
574 i64::MIN..=U8MIN => return Err(int_too_small_error(int, U8MIN, span)),
575 U8MAX..=i64::MAX => return Err(int_too_large_error(int, U8MAX, span)),
576 };
577 }
578 Ok(this)
579 }
580 v => Err(ShellError::CantConvert {
581 to_type: Self::expected_type().to_string(),
582 from_type: v.get_type().to_string(),
583 span: v.span(),
584 help: None,
585 }),
586 }
587 }
588
589 fn expected_type() -> Type {
590 Type::Binary
591 }
592}
593
594impl<T> FromValue for Option<T>
597where
598 T: FromValue,
599{
600 fn from_value(v: Value) -> Result<Self, ShellError> {
601 match v {
602 Value::Nothing { .. } => Ok(None),
603 v => T::from_value(v).map(Option::Some),
604 }
605 }
606
607 fn expected_type() -> Type {
608 T::expected_type()
609 }
610}
611
612impl<A, B> FromValue for Result<A, B>
613where
614 A: FromValue,
615 B: FromValue,
616{
617 fn from_value(v: Value) -> std::result::Result<Self, ShellError> {
618 match (A::from_value(v.clone()), B::from_value(v.clone())) {
619 (Ok(a), _) => Ok(Ok(a)),
620 (_, Ok(b)) => Ok(Err(b)),
621 (Err(ea), Err(_)) => Err(ea),
622 }
623 }
624
625 fn expected_type() -> Type {
626 Type::OneOf(vec![A::expected_type(), B::expected_type()].into())
627 }
628}
629
630impl<B> FromValue for Cow<'_, B>
636where
637 B: ?Sized + ToOwned,
638 B::Owned: FromValue,
639{
640 fn from_value(v: Value) -> Result<Self, ShellError> {
641 <B::Owned as FromValue>::from_value(v).map(Cow::Owned)
642 }
643
644 fn expected_type() -> Type {
645 <B::Owned as FromValue>::expected_type()
646 }
647}
648
649impl<V> FromValue for HashMap<String, V>
650where
651 V: FromValue,
652{
653 fn from_value(v: Value) -> Result<Self, ShellError> {
654 let record = v.into_record()?;
655 let items: Result<Vec<(String, V)>, ShellError> = record
656 .into_iter()
657 .map(|(k, v)| Ok((k, V::from_value(v)?)))
658 .collect();
659 Ok(HashMap::from_iter(items?))
660 }
661
662 fn expected_type() -> Type {
663 Type::Record(vec![].into_boxed_slice())
664 }
665}
666
667impl<T> FromValue for Box<T>
668where
669 T: FromValue,
670{
671 fn from_value(v: Value) -> Result<Self, ShellError> {
672 match T::from_value(v) {
673 Ok(val) => Ok(Box::new(val)),
674 Err(e) => Err(e),
675 }
676 }
677}
678
679impl<T> FromValue for Vec<T>
680where
681 T: FromValue,
682{
683 fn from_value(v: Value) -> Result<Self, ShellError> {
684 match v {
685 Value::List { vals, .. } => vals
686 .into_iter()
687 .map(|v| T::from_value(v))
688 .collect::<Result<Vec<T>, ShellError>>(),
689 v => Err(ShellError::CantConvert {
690 to_type: Self::expected_type().to_string(),
691 from_type: v.get_type().to_string(),
692 span: v.span(),
693 help: None,
694 }),
695 }
696 }
697
698 fn expected_type() -> Type {
699 Type::List(Box::new(T::expected_type()))
700 }
701}
702
703impl FromValue for Value {
706 fn from_value(v: Value) -> Result<Self, ShellError> {
707 Ok(v)
708 }
709
710 fn expected_type() -> Type {
711 Type::Any
712 }
713}
714
715impl FromValue for CellPath {
716 fn from_value(v: Value) -> Result<Self, ShellError> {
717 let span = v.span();
718 match v {
719 Value::CellPath { val, .. } => Ok(val),
720 Value::String { val, .. } => Ok(CellPath {
721 members: vec![PathMember::String {
722 val,
723 span,
724 optional: false,
725 casing: Casing::Sensitive,
726 }],
727 }),
728 Value::Int { val, .. } => {
729 if val.is_negative() {
730 Err(ShellError::NeedsPositiveValue { span })
731 } else {
732 Ok(CellPath {
733 members: vec![PathMember::Int {
734 val: val as usize,
735 span,
736 optional: false,
737 }],
738 })
739 }
740 }
741 x => Err(ShellError::CantConvert {
742 to_type: Self::expected_type().to_string(),
743 from_type: x.get_type().to_string(),
744 span,
745 help: None,
746 }),
747 }
748 }
749
750 fn expected_type() -> Type {
751 Type::CellPath
752 }
753}
754
755impl FromValue for Closure {
756 fn from_value(v: Value) -> Result<Self, ShellError> {
757 match v {
758 Value::Closure { val, .. } => Ok(*val),
759 v => Err(ShellError::CantConvert {
760 to_type: Self::expected_type().to_string(),
761 from_type: v.get_type().to_string(),
762 span: v.span(),
763 help: None,
764 }),
765 }
766 }
767}
768
769impl FromValue for DateTime<FixedOffset> {
770 fn from_value(v: Value) -> Result<Self, ShellError> {
771 match v {
772 Value::Date { val, .. } => Ok(val),
773 v => Err(ShellError::CantConvert {
774 to_type: Self::expected_type().to_string(),
775 from_type: v.get_type().to_string(),
776 span: v.span(),
777 help: None,
778 }),
779 }
780 }
781
782 fn expected_type() -> Type {
783 Type::Date
784 }
785}
786
787impl FromValue for NuGlob {
788 fn from_value(v: Value) -> Result<Self, ShellError> {
789 match v {
791 Value::CellPath { val, .. } => Ok(NuGlob::Expand(val.to_string())),
792 Value::String { val, .. } => Ok(NuGlob::DoNotExpand(val)),
793 Value::Glob {
794 val,
795 no_expand: quoted,
796 ..
797 } => {
798 if quoted {
799 Ok(NuGlob::DoNotExpand(val))
800 } else {
801 Ok(NuGlob::Expand(val))
802 }
803 }
804 v => Err(ShellError::CantConvert {
805 to_type: Self::expected_type().to_string(),
806 from_type: v.get_type().to_string(),
807 span: v.span(),
808 help: None,
809 }),
810 }
811 }
812
813 fn expected_type() -> Type {
814 Type::String
815 }
816}
817
818impl FromValue for Range {
819 fn from_value(v: Value) -> Result<Self, ShellError> {
820 match v {
821 Value::Range { val, .. } => Ok(*val),
822 v => Err(ShellError::CantConvert {
823 to_type: Self::expected_type().to_string(),
824 from_type: v.get_type().to_string(),
825 span: v.span(),
826 help: None,
827 }),
828 }
829 }
830
831 fn expected_type() -> Type {
832 Type::Range
833 }
834}
835
836impl FromValue for Record {
837 fn from_value(v: Value) -> Result<Self, ShellError> {
838 match v {
839 Value::Record { val, .. } => Ok(val.into_owned()),
840 v => Err(ShellError::CantConvert {
841 to_type: Self::expected_type().to_string(),
842 from_type: v.get_type().to_string(),
843 span: v.span(),
844 help: None,
845 }),
846 }
847 }
848}
849
850impl<T> FromValue for Spanned<T>
853where
854 T: FromValue,
855{
856 fn from_value(v: Value) -> Result<Self, ShellError> {
857 let span = v.span();
858 Ok(Spanned {
859 item: T::from_value(v)?,
860 span,
861 })
862 }
863
864 fn expected_type() -> Type {
865 T::expected_type()
866 }
867}
868
869impl FromValue for bytes::Bytes {
872 fn from_value(v: Value) -> Result<Self, ShellError> {
873 match v {
874 Value::Binary { val, .. } => Ok(val.into()),
875 v => Err(ShellError::CantConvert {
876 to_type: Self::expected_type().to_string(),
877 from_type: v.get_type().to_string(),
878 span: v.span(),
879 help: None,
880 }),
881 }
882 }
883
884 fn expected_type() -> Type {
885 Type::Binary
886 }
887}
888
889fn int_too_small_error(int: impl fmt::Display, min: impl fmt::Display, span: Span) -> ShellError {
891 ShellError::Generic(GenericError::new(
892 "Integer too small",
893 format!("{int} is smaller than {min}"),
894 span,
895 ))
896}
897
898fn int_too_large_error(int: impl fmt::Display, max: impl fmt::Display, span: Span) -> ShellError {
899 ShellError::Generic(GenericError::new(
900 "Integer too large",
901 format!("{int} is larger than {max}"),
902 span,
903 ))
904}
905
906#[cfg(test)]
907mod tests {
908 use crate::{
909 FromValue, IntoValue, Record, Span, Type, Value,
910 ast::{CellPath, PathMember},
911 casing::Casing,
912 engine::Closure,
913 };
914 use std::ffi::OsString;
915 use std::ops::Deref;
916
917 #[test]
918 fn expected_type_default_impl() {
919 assert_eq!(
920 Record::expected_type(),
921 Type::Custom("Record".to_string().into_boxed_str())
922 );
923
924 assert_eq!(
925 Closure::expected_type(),
926 Type::Custom("Closure".to_string().into_boxed_str())
927 );
928 }
929
930 #[test]
931 fn from_value_vec_u8() {
932 let vec: Vec<u8> = vec![1, 2, 3];
933 let span = Span::test_data();
934 let string = "Hello Vec<u8>!".to_string();
935
936 assert_eq!(
937 Vec::<u8>::from_value(vec.clone().into_value(span)).unwrap(),
938 vec.clone(),
939 "Vec<u8> roundtrip"
940 );
941
942 assert_eq!(
943 Vec::<u8>::from_value(Value::test_string(string.clone()))
944 .unwrap()
945 .deref(),
946 string.as_bytes(),
947 "Vec<u8> from String"
948 );
949
950 assert_eq!(
951 Vec::<u8>::from_value(Value::test_binary(vec.clone())).unwrap(),
952 vec,
953 "Vec<u8> from Binary"
954 );
955
956 assert!(Vec::<u8>::from_value(vec![u8::MIN as i32 - 1].into_value(span)).is_err());
957 assert!(Vec::<u8>::from_value(vec![u8::MAX as i32 + 1].into_value(span)).is_err());
958 }
959
960 #[test]
961 fn from_value_os_string() {
962 let span = Span::test_data();
963 let expected = OsString::from("hello");
964
965 assert_eq!(
967 OsString::from_value(Value::test_string("hello".to_string())).unwrap(),
968 expected
969 );
970
971 let cp_val = Value::test_cell_path(CellPath {
974 members: vec![PathMember::String {
975 val: "hello".into(),
976 span,
977 optional: false,
978 casing: Casing::Sensitive,
979 }],
980 });
981 assert_eq!(
982 OsString::from_value(cp_val).unwrap(),
983 OsString::from("$.hello")
984 );
985 }
986}