1use std::borrow::Cow;
7
8use yog_core::{BlockPos, Point};
9use yog_data::Atom;
10
11pub trait Arg<T> {
13 fn arg(self) -> T;
14}
15
16impl<T> Arg<T> for T {
17 fn arg(self) -> T {
18 self
19 }
20}
21
22macro_rules! args {
23 ($($from:ty => $to:ty, |$v:ident| $make:expr;)*) => {
24 $(impl Arg<$to> for $from {
25 fn arg(self) -> $to {
26 let $v = self;
27 $make
28 }
29 })*
30 };
31}
32
33args! {
34 &str => String, |s| s.to_owned();
35 &String => String, |s| s.clone();
36 Cow<'_, str> => String, |s| s.into_owned();
37 Atom => String, |a| a.as_str().to_owned();
38 &Atom => String, |a| a.as_str().to_owned();
39 Option<&str> => Option<String>, |s| s.map(str::to_owned);
40 Option<&String> => Option<String>, |s| s.cloned();
41 &[u8] => Vec<u8>, |b| b.to_vec();
42 &Vec<u8> => Vec<u8>, |b| b.clone();
43 &[&str] => Vec<String>, |l| l.iter().map(|s| (*s).to_owned()).collect();
44 Vec<&str> => Vec<String>, |l| l.into_iter().map(str::to_owned).collect();
45 &[String] => Vec<String>, |l| l.to_vec();
46 [i32; 3] => BlockPos, |p| p.into();
47 (i32, i32, i32) => BlockPos, |p| p.into();
48 [f64; 3] => Point, |p| p.into();
49 (f64, f64, f64) => Point, |p| p.into();
50 BlockPos => Point, |p| p.into();
51}
52
53impl<const N: usize> Arg<Vec<u8>> for &[u8; N] {
55 fn arg(self) -> Vec<u8> {
56 self.to_vec()
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63
64 fn take<T>(v: impl Arg<T>) -> T {
65 v.arg()
66 }
67
68 #[test]
69 fn a_literal_is_the_number_taken_and_text_any_string() {
70 let n: u32 = take(1);
71 assert_eq!(n, 1);
72 let s: String = take("a");
73 assert_eq!(s, "a");
74 let p: BlockPos = take([1, 2, 3]);
75 assert_eq!(p, BlockPos::new(1, 2, 3));
76 let o: Option<String> = take(Some("u"));
77 assert_eq!(o.as_deref(), Some("u"));
78 }
79}