use crate::object::base as value; use crate::prelude::*; use log::trace; pub trait ExtractType: Sized { fn extract(value: &Tagged) -> Result; } impl ExtractType for T { default fn extract(_value: &Tagged) -> Result { let name = std::any::type_name::(); Err(ShellError::unimplemented(format!( " ExtractType for {}", name ))) } } impl ExtractType for Vec> { fn extract(value: &Tagged) -> Result { let name = std::any::type_name::(); trace!(" Extracting {:?} for Vec<{}>", value, name); match value.item() { Value::List(items) => { let mut out = vec![]; for item in items { out.push(T::extract(item)?.tagged(item.tag())); } Ok(out) } other => Err(ShellError::type_error( "Vec", other.type_name().tagged(value.tag()), )), } } } impl ExtractType for (T, U) { fn extract(value: &Tagged) -> Result<(T, U), ShellError> { let t_name = std::any::type_name::(); let u_name = std::any::type_name::(); trace!("Extracting {:?} for ({}, {})", value, t_name, u_name); match value.item() { Value::List(items) => { if items.len() == 2 { let first = &items[0]; let second = &items[1]; Ok((T::extract(first)?, U::extract(second)?)) } else { Err(ShellError::type_error( "two-element-tuple", "not-two".tagged(value.tag()), )) } } other => Err(ShellError::type_error( "two-element-tuple", other.type_name().tagged(value.tag()), )), } } } impl ExtractType for Option { fn extract(value: &Tagged) -> Result, ShellError> { let name = std::any::type_name::(); trace!("