1use super::values::{
2 matches_array_handle_type, matches_array_type, matches_function_handle_type, matches_lust_enum,
3 matches_lust_struct, matches_map_handle_type, ArrayHandle, EnumInstance, FunctionHandle,
4 MapHandle, StringRef, StructHandle, StructInstance, TypedValue, ValueRef,
5};
6use crate::ast::{Span, Type, TypeKind};
7use crate::bytecode::Value;
8use crate::number::{LustFloat, LustInt};
9use crate::{LustError, Result};
10use std::rc::Rc;
11
12fn struct_field_type_error(field: &str, expected: &str, actual: &Value) -> LustError {
13 LustError::TypeError {
14 message: format!(
15 "Struct field '{}' expects '{}' but received value of type '{:?}'",
16 field,
17 expected,
18 actual.type_of()
19 ),
20 }
21}
22
23pub trait FromStructField<'a>: Sized {
24 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self>;
25}
26
27impl<'a> FromStructField<'a> for ValueRef<'a> {
28 fn from_value(_field: &str, value: ValueRef<'a>) -> Result<Self> {
29 Ok(value)
30 }
31}
32
33impl<'a> FromStructField<'a> for StructHandle {
34 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
35 value
36 .as_struct_handle()
37 .ok_or_else(|| struct_field_type_error(field, "struct", value.as_value()))
38 }
39}
40
41impl<'a> FromStructField<'a> for StructInstance {
42 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
43 value
44 .as_struct_handle()
45 .map(|handle| handle.to_instance())
46 .ok_or_else(|| struct_field_type_error(field, "struct", value.as_value()))
47 }
48}
49
50impl<'a> FromStructField<'a> for ArrayHandle {
51 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
52 value
53 .as_array_handle()
54 .ok_or_else(|| struct_field_type_error(field, "array", value.as_value()))
55 }
56}
57
58impl<'a> FromStructField<'a> for MapHandle {
59 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
60 value
61 .as_map_handle()
62 .ok_or_else(|| struct_field_type_error(field, "map", value.as_value()))
63 }
64}
65
66impl<'a> FromStructField<'a> for FunctionHandle {
67 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
68 let owned = value.to_owned();
69 FunctionHandle::from_value(owned)
70 .map_err(|_| struct_field_type_error(field, "function", value.as_value()))
71 }
72}
73
74impl<'a> FromStructField<'a> for LustInt {
75 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
76 value
77 .as_int()
78 .ok_or_else(|| struct_field_type_error(field, "int", value.as_value()))
79 }
80}
81
82impl<'a> FromStructField<'a> for LustFloat {
83 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
84 value
85 .as_float()
86 .ok_or_else(|| struct_field_type_error(field, "float", value.as_value()))
87 }
88}
89
90impl<'a> FromStructField<'a> for bool {
91 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
92 value
93 .as_bool()
94 .ok_or_else(|| struct_field_type_error(field, "bool", value.as_value()))
95 }
96}
97
98impl<'a> FromStructField<'a> for Rc<String> {
99 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
100 value
101 .as_rc_string()
102 .ok_or_else(|| struct_field_type_error(field, "string", value.as_value()))
103 }
104}
105
106impl<'a> FromStructField<'a> for Value {
107 fn from_value(_field: &str, value: ValueRef<'a>) -> Result<Self> {
108 Ok(value.into_owned())
109 }
110}
111
112impl<'a, T> FromStructField<'a> for Option<T>
113where
114 T: FromStructField<'a>,
115{
116 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
117 if matches!(value.as_value(), Value::Nil) {
118 Ok(None)
119 } else {
120 T::from_value(field, value).map(Some)
121 }
122 }
123}
124
125impl<'a> FromStructField<'a> for StringRef<'a> {
126 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
127 if value.as_string().is_some() {
128 Ok(StringRef::new(value))
129 } else {
130 Err(struct_field_type_error(field, "string", value.as_value()))
131 }
132 }
133}
134
135impl<'a> FromStructField<'a> for EnumInstance {
136 fn from_value(field: &str, value: ValueRef<'a>) -> Result<Self> {
137 match value.as_value() {
138 Value::Enum { .. } => <EnumInstance as FromLustValue>::from_value(value.into_owned()),
139 other => Err(struct_field_type_error(field, "enum", other)),
140 }
141 }
142}
143
144pub trait LustStructView<'a>: Sized {
145 const TYPE_NAME: &'static str;
146
147 fn from_handle(handle: &'a StructHandle) -> Result<Self>;
148}
149
150pub trait IntoTypedValue {
151 fn into_typed_value(self) -> TypedValue;
152}
153
154impl IntoTypedValue for Value {
155 fn into_typed_value(self) -> TypedValue {
156 TypedValue::new(self, |_value, _ty| true, "Value")
157 }
158}
159
160impl IntoTypedValue for StructInstance {
161 fn into_typed_value(self) -> TypedValue {
162 let value = self.into_value();
163 TypedValue::new(value, |v, ty| matches_lust_struct(v, ty), "struct")
164 }
165}
166
167impl IntoTypedValue for StructHandle {
168 fn into_typed_value(self) -> TypedValue {
169 <StructInstance as IntoTypedValue>::into_typed_value(self.into_instance())
170 }
171}
172
173impl IntoTypedValue for EnumInstance {
174 fn into_typed_value(self) -> TypedValue {
175 let value = self.into_value();
176 TypedValue::new(value, |v, ty| matches_lust_enum(v, ty), "enum")
177 }
178}
179
180impl IntoTypedValue for FunctionHandle {
181 fn into_typed_value(self) -> TypedValue {
182 let value = self.into_value();
183 TypedValue::new(value, |_v, ty| matches_function_handle_type(ty), "function")
184 }
185}
186
187macro_rules! impl_into_typed_for_primitive {
188 ($ty:ty, $desc:expr, $matcher:expr) => {
189 impl IntoTypedValue for $ty {
190 fn into_typed_value(self) -> TypedValue {
191 let value = self.into_value();
192 TypedValue::new(value, $matcher, $desc)
193 }
194 }
195 };
196}
197
198impl_into_typed_for_primitive!(LustInt, "int", |_, ty: &Type| match &ty.kind {
199 TypeKind::Int | TypeKind::Unknown => true,
200 TypeKind::Union(types) => types
201 .iter()
202 .any(|alt| matches!(&alt.kind, TypeKind::Int | TypeKind::Unknown)),
203 _ => false,
204});
205impl_into_typed_for_primitive!(LustFloat, "float", |_, ty: &Type| match &ty.kind {
206 TypeKind::Float | TypeKind::Unknown => true,
207 TypeKind::Union(types) => types
208 .iter()
209 .any(|alt| matches!(&alt.kind, TypeKind::Float | TypeKind::Unknown)),
210 _ => false,
211});
212impl_into_typed_for_primitive!(bool, "bool", |_, ty: &Type| match &ty.kind {
213 TypeKind::Bool | TypeKind::Unknown => true,
214 TypeKind::Union(types) => types
215 .iter()
216 .any(|alt| matches!(&alt.kind, TypeKind::Bool | TypeKind::Unknown)),
217 _ => false,
218});
219impl IntoTypedValue for String {
220 fn into_typed_value(self) -> TypedValue {
221 let value = self.into_value();
222 TypedValue::new(value, string_matcher, "string")
223 }
224}
225
226impl<'a> IntoTypedValue for &'a str {
227 fn into_typed_value(self) -> TypedValue {
228 let value = self.into_value();
229 TypedValue::new(value, string_matcher, "string")
230 }
231}
232
233impl<'a> IntoTypedValue for &'a String {
234 fn into_typed_value(self) -> TypedValue {
235 let value = self.into_value();
236 TypedValue::new(value, string_matcher, "string")
237 }
238}
239
240impl IntoTypedValue for () {
241 fn into_typed_value(self) -> TypedValue {
242 TypedValue::new(
243 Value::Nil,
244 |_, ty| matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown),
245 "unit",
246 )
247 }
248}
249
250impl<T> IntoTypedValue for Vec<T>
251where
252 T: IntoLustValue,
253{
254 fn into_typed_value(self) -> TypedValue {
255 let values = self.into_iter().map(|item| item.into_value()).collect();
256 TypedValue::new(
257 Value::array(values),
258 |_, ty| matches_array_type(ty, &T::matches_lust_type),
259 "array",
260 )
261 }
262}
263
264impl IntoTypedValue for ArrayHandle {
265 fn into_typed_value(self) -> TypedValue {
266 let value = self.into_value();
267 TypedValue::new(value, |_, ty| matches_array_handle_type(ty), "array")
268 }
269}
270
271impl IntoTypedValue for MapHandle {
272 fn into_typed_value(self) -> TypedValue {
273 let value = self.into_value();
274 TypedValue::new(value, |_, ty| matches_map_handle_type(ty), "map")
275 }
276}
277
278fn string_matcher(_: &Value, ty: &Type) -> bool {
279 match &ty.kind {
280 TypeKind::String | TypeKind::Unknown => true,
281 TypeKind::Union(types) => types
282 .iter()
283 .any(|alt| matches!(&alt.kind, TypeKind::String | TypeKind::Unknown)),
284 _ => false,
285 }
286}
287
288pub trait FromLustArgs: Sized {
289 fn from_values(values: &[Value]) -> std::result::Result<Self, String>;
290 fn matches_signature(params: &[Type]) -> bool;
291}
292
293macro_rules! impl_from_lust_args_tuple {
294 ($( $name:ident ),+) => {
295 impl<$($name),+> FromLustArgs for ($($name,)+)
296 where
297 $($name: FromLustValue,)+
298 {
299 fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
300 let expected = count_idents!($($name),+);
301 if values.len() != expected {
302 return Err(format!(
303 "Native function expected {} argument(s) but received {}",
304 expected,
305 values.len()
306 ));
307 }
308
309 let mut idx = 0;
310 let result = (
311 $(
312 {
313 let value = $name::from_value(values[idx].clone()).map_err(|e| e.to_string())?;
314 idx += 1;
315 value
316 },
317 )+
318 );
319 let _ = idx;
320 Ok(result)
321 }
322
323 fn matches_signature(params: &[Type]) -> bool {
324 let expected = count_idents!($($name),+);
325 params.len() == expected && {
326 let mut idx = 0;
327 let mut ok = true;
328 $(
329 if ok && !$name::matches_lust_type(¶ms[idx]) {
330 ok = false;
331 }
332
333 idx += 1;
334 )+
335 let _ = idx;
336 ok
337 }
338
339 }
340
341 }
342
343 };
344}
345
346macro_rules! count_idents {
347 ($($name:ident),*) => {
348 <[()]>::len(&[$(count_idents!(@sub $name)),*])
349 };
350 (@sub $name:ident) => { () };
351}
352
353impl_from_lust_args_tuple!(A);
354impl_from_lust_args_tuple!(A, B);
355impl_from_lust_args_tuple!(A, B, C);
356impl_from_lust_args_tuple!(A, B, C, D);
357impl_from_lust_args_tuple!(A, B, C, D, E);
358impl<T> FromLustArgs for T
359where
360 T: FromLustValue,
361{
362 fn from_values(values: &[Value]) -> std::result::Result<Self, String> {
363 match values.len() {
364 0 => T::from_value(Value::Nil).map_err(|e| e.to_string()),
365 1 => T::from_value(values[0].clone()).map_err(|e| e.to_string()),
366 count => Err(format!(
367 "Native function expected 1 argument but received {}",
368 count
369 )),
370 }
371 }
372
373 fn matches_signature(params: &[Type]) -> bool {
374 if params.is_empty() {
375 let unit = Type::new(TypeKind::Unit, Span::new(0, 0, 0, 0));
376 return T::matches_lust_type(&unit);
377 }
378
379 params.len() == 1 && T::matches_lust_type(¶ms[0])
380 }
381}
382
383pub trait IntoLustValue: Sized {
384 fn into_value(self) -> Value;
385 fn matches_lust_type(ty: &Type) -> bool;
386 fn type_description() -> &'static str;
387}
388
389pub trait FromLustValue: Sized {
390 fn from_value(value: Value) -> Result<Self>;
391 fn matches_lust_type(ty: &Type) -> bool;
392 fn type_description() -> &'static str;
393}
394
395pub trait FunctionArgs {
396 fn into_values(self) -> Vec<Value>;
397 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()>;
398}
399
400impl IntoLustValue for Value {
401 fn into_value(self) -> Value {
402 self
403 }
404
405 fn matches_lust_type(_: &Type) -> bool {
406 true
407 }
408
409 fn type_description() -> &'static str {
410 "Value"
411 }
412}
413
414impl FromLustValue for Value {
415 fn from_value(value: Value) -> Result<Self> {
416 Ok(value)
417 }
418
419 fn matches_lust_type(_: &Type) -> bool {
420 true
421 }
422
423 fn type_description() -> &'static str {
424 "Value"
425 }
426}
427
428impl IntoLustValue for LustInt {
429 fn into_value(self) -> Value {
430 Value::Int(self)
431 }
432
433 fn matches_lust_type(ty: &Type) -> bool {
434 matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
435 }
436
437 fn type_description() -> &'static str {
438 "int"
439 }
440}
441
442impl FromLustValue for LustInt {
443 fn from_value(value: Value) -> Result<Self> {
444 match value {
445 Value::Int(v) => Ok(v),
446 other => Err(LustError::RuntimeError {
447 message: format!("Expected Lust value 'int' but received '{:?}'", other),
448 }),
449 }
450 }
451
452 fn matches_lust_type(ty: &Type) -> bool {
453 matches!(ty.kind, TypeKind::Int | TypeKind::Unknown)
454 }
455
456 fn type_description() -> &'static str {
457 "int"
458 }
459}
460
461impl IntoLustValue for LustFloat {
462 fn into_value(self) -> Value {
463 Value::Float(self)
464 }
465
466 fn matches_lust_type(ty: &Type) -> bool {
467 matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
468 }
469
470 fn type_description() -> &'static str {
471 "float"
472 }
473}
474
475impl FromLustValue for LustFloat {
476 fn from_value(value: Value) -> Result<Self> {
477 match value {
478 Value::Float(v) => Ok(v),
479 other => Err(LustError::RuntimeError {
480 message: format!("Expected Lust value 'float' but received '{:?}'", other),
481 }),
482 }
483 }
484
485 fn matches_lust_type(ty: &Type) -> bool {
486 matches!(ty.kind, TypeKind::Float | TypeKind::Unknown)
487 }
488
489 fn type_description() -> &'static str {
490 "float"
491 }
492}
493
494impl IntoLustValue for bool {
495 fn into_value(self) -> Value {
496 Value::Bool(self)
497 }
498
499 fn matches_lust_type(ty: &Type) -> bool {
500 matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
501 }
502
503 fn type_description() -> &'static str {
504 "bool"
505 }
506}
507
508impl FromLustValue for bool {
509 fn from_value(value: Value) -> Result<Self> {
510 match value {
511 Value::Bool(b) => Ok(b),
512 other => Err(LustError::RuntimeError {
513 message: format!("Expected Lust value 'bool' but received '{:?}'", other),
514 }),
515 }
516 }
517
518 fn matches_lust_type(ty: &Type) -> bool {
519 matches!(ty.kind, TypeKind::Bool | TypeKind::Unknown)
520 }
521
522 fn type_description() -> &'static str {
523 "bool"
524 }
525}
526
527impl IntoLustValue for String {
528 fn into_value(self) -> Value {
529 Value::String(Rc::new(self))
530 }
531
532 fn matches_lust_type(ty: &Type) -> bool {
533 matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
534 }
535
536 fn type_description() -> &'static str {
537 "string"
538 }
539}
540
541impl IntoLustValue for Rc<String> {
542 fn into_value(self) -> Value {
543 Value::String(self)
544 }
545
546 fn matches_lust_type(ty: &Type) -> bool {
547 matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
548 }
549
550 fn type_description() -> &'static str {
551 "string"
552 }
553}
554
555impl IntoLustValue for StructInstance {
556 fn into_value(self) -> Value {
557 self.into_value()
558 }
559
560 fn matches_lust_type(ty: &Type) -> bool {
561 match &ty.kind {
562 TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
563 TypeKind::Union(types) => types
564 .iter()
565 .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
566 _ => false,
567 }
568 }
569
570 fn type_description() -> &'static str {
571 "struct"
572 }
573}
574
575impl IntoLustValue for StructHandle {
576 fn into_value(self) -> Value {
577 <StructInstance as IntoLustValue>::into_value(self.into_instance())
578 }
579
580 fn matches_lust_type(ty: &Type) -> bool {
581 <StructInstance as IntoLustValue>::matches_lust_type(ty)
582 }
583
584 fn type_description() -> &'static str {
585 <StructInstance as IntoLustValue>::type_description()
586 }
587}
588
589impl IntoLustValue for FunctionHandle {
590 fn into_value(self) -> Value {
591 self.into_value()
592 }
593
594 fn matches_lust_type(ty: &Type) -> bool {
595 matches_function_handle_type(ty)
596 }
597
598 fn type_description() -> &'static str {
599 "function"
600 }
601}
602
603impl FromLustValue for StructInstance {
604 fn from_value(value: Value) -> Result<Self> {
605 match &value {
606 Value::Struct { name, .. } => Ok(StructInstance::new(name.clone(), value)),
607 other => Err(LustError::RuntimeError {
608 message: format!("Expected Lust value 'struct' but received '{:?}'", other),
609 }),
610 }
611 }
612
613 fn matches_lust_type(ty: &Type) -> bool {
614 match &ty.kind {
615 TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
616 TypeKind::Union(types) => types
617 .iter()
618 .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
619 _ => false,
620 }
621 }
622
623 fn type_description() -> &'static str {
624 "struct"
625 }
626}
627
628impl FromLustValue for StructHandle {
629 fn from_value(value: Value) -> Result<Self> {
630 <StructInstance as FromLustValue>::from_value(value).map(StructHandle::from)
631 }
632
633 fn matches_lust_type(ty: &Type) -> bool {
634 <StructInstance as FromLustValue>::matches_lust_type(ty)
635 }
636
637 fn type_description() -> &'static str {
638 <StructInstance as FromLustValue>::type_description()
639 }
640}
641
642impl FromLustValue for FunctionHandle {
643 fn from_value(value: Value) -> Result<Self> {
644 if FunctionHandle::is_callable_value(&value) {
645 Ok(FunctionHandle::new_unchecked(value))
646 } else {
647 Err(LustError::RuntimeError {
648 message: format!("Expected Lust value 'function' but received '{:?}'", value),
649 })
650 }
651 }
652
653 fn matches_lust_type(ty: &Type) -> bool {
654 matches_function_handle_type(ty)
655 }
656
657 fn type_description() -> &'static str {
658 "function"
659 }
660}
661
662impl IntoLustValue for EnumInstance {
663 fn into_value(self) -> Value {
664 self.into_value()
665 }
666
667 fn matches_lust_type(ty: &Type) -> bool {
668 match &ty.kind {
669 TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
670 TypeKind::Union(types) => types
671 .iter()
672 .any(|alt| <Self as IntoLustValue>::matches_lust_type(alt)),
673 _ => false,
674 }
675 }
676
677 fn type_description() -> &'static str {
678 "enum"
679 }
680}
681
682impl FromLustValue for EnumInstance {
683 fn from_value(value: Value) -> Result<Self> {
684 match &value {
685 Value::Enum {
686 enum_name, variant, ..
687 } => Ok(EnumInstance::new(enum_name.clone(), variant.clone(), value)),
688 other => Err(LustError::RuntimeError {
689 message: format!("Expected Lust value 'enum' but received '{:?}'", other),
690 }),
691 }
692 }
693
694 fn matches_lust_type(ty: &Type) -> bool {
695 match &ty.kind {
696 TypeKind::Unknown | TypeKind::Named(_) | TypeKind::GenericInstance { .. } => true,
697 TypeKind::Union(types) => types
698 .iter()
699 .any(|alt| <Self as FromLustValue>::matches_lust_type(alt)),
700 _ => false,
701 }
702 }
703
704 fn type_description() -> &'static str {
705 "enum"
706 }
707}
708
709impl<T> IntoLustValue for Vec<T>
710where
711 T: IntoLustValue,
712{
713 fn into_value(self) -> Value {
714 let values = self.into_iter().map(|item| item.into_value()).collect();
715 Value::array(values)
716 }
717
718 fn matches_lust_type(ty: &Type) -> bool {
719 matches_array_type(ty, &T::matches_lust_type)
720 }
721
722 fn type_description() -> &'static str {
723 "array"
724 }
725}
726
727impl IntoLustValue for ArrayHandle {
728 fn into_value(self) -> Value {
729 self.into_value()
730 }
731
732 fn matches_lust_type(ty: &Type) -> bool {
733 matches_array_handle_type(ty)
734 }
735
736 fn type_description() -> &'static str {
737 "array"
738 }
739}
740
741impl IntoLustValue for MapHandle {
742 fn into_value(self) -> Value {
743 self.into_value()
744 }
745
746 fn matches_lust_type(ty: &Type) -> bool {
747 matches_map_handle_type(ty)
748 }
749
750 fn type_description() -> &'static str {
751 "map"
752 }
753}
754
755impl<T> FromLustValue for Vec<T>
756where
757 T: FromLustValue,
758{
759 fn from_value(value: Value) -> Result<Self> {
760 match value {
761 Value::Array(items) => {
762 let borrowed = items.borrow();
763 let mut result = Vec::with_capacity(borrowed.len());
764 for item in borrowed.iter() {
765 result.push(T::from_value(item.clone())?);
766 }
767
768 Ok(result)
769 }
770
771 other => Err(LustError::RuntimeError {
772 message: format!("Expected Lust value 'array' but received '{:?}'", other),
773 }),
774 }
775 }
776
777 fn matches_lust_type(ty: &Type) -> bool {
778 matches_array_type(ty, &T::matches_lust_type)
779 }
780
781 fn type_description() -> &'static str {
782 "array"
783 }
784}
785
786impl FromLustValue for ArrayHandle {
787 fn from_value(value: Value) -> Result<Self> {
788 match value {
789 Value::Array(items) => Ok(ArrayHandle::from_rc(items)),
790 other => Err(LustError::RuntimeError {
791 message: format!("Expected Lust value 'array' but received '{:?}'", other),
792 }),
793 }
794 }
795
796 fn matches_lust_type(ty: &Type) -> bool {
797 matches_array_handle_type(ty)
798 }
799
800 fn type_description() -> &'static str {
801 "array"
802 }
803}
804
805impl FromLustValue for MapHandle {
806 fn from_value(value: Value) -> Result<Self> {
807 match value {
808 Value::Map(map) => Ok(MapHandle::from_rc(map)),
809 other => Err(LustError::RuntimeError {
810 message: format!("Expected Lust value 'map' but received '{:?}'", other),
811 }),
812 }
813 }
814
815 fn matches_lust_type(ty: &Type) -> bool {
816 matches_map_handle_type(ty)
817 }
818
819 fn type_description() -> &'static str {
820 "map"
821 }
822}
823
824impl<'a> IntoLustValue for &'a str {
825 fn into_value(self) -> Value {
826 Value::String(Rc::new(self.to_owned()))
827 }
828
829 fn matches_lust_type(ty: &Type) -> bool {
830 matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
831 }
832
833 fn type_description() -> &'static str {
834 "string"
835 }
836}
837
838impl<'a> IntoLustValue for &'a String {
839 fn into_value(self) -> Value {
840 Value::String(Rc::new(self.clone()))
841 }
842
843 fn matches_lust_type(ty: &Type) -> bool {
844 matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
845 }
846
847 fn type_description() -> &'static str {
848 "string"
849 }
850}
851
852impl FromLustValue for String {
853 fn from_value(value: Value) -> Result<Self> {
854 match value {
855 Value::String(s) => Ok((*s).clone()),
856 other => Err(LustError::RuntimeError {
857 message: format!("Expected Lust value 'string' but received '{:?}'", other),
858 }),
859 }
860 }
861
862 fn matches_lust_type(ty: &Type) -> bool {
863 matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
864 }
865
866 fn type_description() -> &'static str {
867 "string"
868 }
869}
870
871impl FromLustValue for Rc<String> {
872 fn from_value(value: Value) -> Result<Self> {
873 match value {
874 Value::String(s) => Ok(s),
875 other => Err(LustError::RuntimeError {
876 message: format!("Expected Lust value 'string' but received '{:?}'", other),
877 }),
878 }
879 }
880
881 fn matches_lust_type(ty: &Type) -> bool {
882 matches!(ty.kind, TypeKind::String | TypeKind::Unknown)
883 }
884
885 fn type_description() -> &'static str {
886 "string"
887 }
888}
889
890impl FromLustValue for () {
891 fn from_value(value: Value) -> Result<Self> {
892 match value {
893 Value::Nil => Ok(()),
894 other => Err(LustError::RuntimeError {
895 message: format!("Expected Lust value 'unit' but received '{:?}'", other),
896 }),
897 }
898 }
899
900 fn matches_lust_type(ty: &Type) -> bool {
901 matches!(ty.kind, TypeKind::Unit | TypeKind::Unknown)
902 }
903
904 fn type_description() -> &'static str {
905 "unit"
906 }
907}
908
909impl FunctionArgs for () {
910 fn into_values(self) -> Vec<Value> {
911 Vec::new()
912 }
913
914 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
915 ensure_arity(function_name, params, 0)
916 }
917}
918
919impl<T> FunctionArgs for T
920where
921 T: IntoLustValue,
922{
923 fn into_values(self) -> Vec<Value> {
924 vec![self.into_value()]
925 }
926
927 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
928 ensure_arity(function_name, params, 1)?;
929 ensure_arg_type::<T>(function_name, params, 0)
930 }
931}
932
933impl<A, B> FunctionArgs for (A, B)
934where
935 A: IntoLustValue,
936 B: IntoLustValue,
937{
938 fn into_values(self) -> Vec<Value> {
939 vec![self.0.into_value(), self.1.into_value()]
940 }
941
942 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
943 ensure_arity(function_name, params, 2)?;
944 ensure_arg_type::<A>(function_name, params, 0)?;
945 ensure_arg_type::<B>(function_name, params, 1)?;
946 Ok(())
947 }
948}
949
950impl<A, B, C> FunctionArgs for (A, B, C)
951where
952 A: IntoLustValue,
953 B: IntoLustValue,
954 C: IntoLustValue,
955{
956 fn into_values(self) -> Vec<Value> {
957 vec![
958 self.0.into_value(),
959 self.1.into_value(),
960 self.2.into_value(),
961 ]
962 }
963
964 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
965 ensure_arity(function_name, params, 3)?;
966 ensure_arg_type::<A>(function_name, params, 0)?;
967 ensure_arg_type::<B>(function_name, params, 1)?;
968 ensure_arg_type::<C>(function_name, params, 2)?;
969 Ok(())
970 }
971}
972
973impl<A, B, C, D> FunctionArgs for (A, B, C, D)
974where
975 A: IntoLustValue,
976 B: IntoLustValue,
977 C: IntoLustValue,
978 D: IntoLustValue,
979{
980 fn into_values(self) -> Vec<Value> {
981 vec![
982 self.0.into_value(),
983 self.1.into_value(),
984 self.2.into_value(),
985 self.3.into_value(),
986 ]
987 }
988
989 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
990 ensure_arity(function_name, params, 4)?;
991 ensure_arg_type::<A>(function_name, params, 0)?;
992 ensure_arg_type::<B>(function_name, params, 1)?;
993 ensure_arg_type::<C>(function_name, params, 2)?;
994 ensure_arg_type::<D>(function_name, params, 3)?;
995 Ok(())
996 }
997}
998
999impl<A, B, C, D, E> FunctionArgs for (A, B, C, D, E)
1000where
1001 A: IntoLustValue,
1002 B: IntoLustValue,
1003 C: IntoLustValue,
1004 D: IntoLustValue,
1005 E: IntoLustValue,
1006{
1007 fn into_values(self) -> Vec<Value> {
1008 vec![
1009 self.0.into_value(),
1010 self.1.into_value(),
1011 self.2.into_value(),
1012 self.3.into_value(),
1013 self.4.into_value(),
1014 ]
1015 }
1016
1017 fn validate_signature(function_name: &str, params: &[Type]) -> Result<()> {
1018 ensure_arity(function_name, params, 5)?;
1019 ensure_arg_type::<A>(function_name, params, 0)?;
1020 ensure_arg_type::<B>(function_name, params, 1)?;
1021 ensure_arg_type::<C>(function_name, params, 2)?;
1022 ensure_arg_type::<D>(function_name, params, 3)?;
1023 ensure_arg_type::<E>(function_name, params, 4)?;
1024 Ok(())
1025 }
1026}
1027
1028fn ensure_arity(function_name: &str, params: &[Type], provided: usize) -> Result<()> {
1029 if params.len() == provided {
1030 Ok(())
1031 } else {
1032 Err(LustError::TypeError {
1033 message: format!(
1034 "Function '{}' expects {} argument(s) but {} were supplied",
1035 function_name,
1036 params.len(),
1037 provided
1038 ),
1039 })
1040 }
1041}
1042
1043fn ensure_arg_type<T: IntoLustValue>(
1044 function_name: &str,
1045 params: &[Type],
1046 index: usize,
1047) -> Result<()> {
1048 if <T as IntoLustValue>::matches_lust_type(¶ms[index]) {
1049 Ok(())
1050 } else {
1051 Err(argument_type_mismatch(
1052 function_name,
1053 index,
1054 <T as IntoLustValue>::type_description(),
1055 ¶ms[index],
1056 ))
1057 }
1058}
1059
1060fn argument_type_mismatch(
1061 function_name: &str,
1062 index: usize,
1063 rust_type: &str,
1064 lust_type: &Type,
1065) -> LustError {
1066 LustError::TypeError {
1067 message: format!(
1068 "Function '{}' parameter {} expects Lust type '{}' but Rust provided '{}'",
1069 function_name,
1070 index + 1,
1071 lust_type,
1072 rust_type
1073 ),
1074 }
1075}