1use yog_data::Value;
4
5use super::{Handle, Nanite};
6
7pub trait Java: Sized {
9 fn desc() -> String;
11 fn to_value(&self) -> Value;
12 fn from_value(v: Value) -> Option<Self>;
13}
14
15pub trait Reply: Sized {
18 fn desc() -> String;
20 fn from_reply(v: Option<Value>) -> Self;
21}
22
23const VOID: &str = "V";
25const STRING: &str = "Ljava/lang/String;";
26
27macro_rules! ints {
28 ($($t:ty => $desc:literal),* $(,)?) => {$(
29 impl Java for $t {
30 fn desc() -> String {
31 $desc.to_owned()
32 }
33 fn to_value(&self) -> Value {
34 Value::Int(i64::from(*self))
35 }
36 fn from_value(v: Value) -> Option<Self> {
37 match v {
38 Value::Int(n) => <$t>::try_from(n).ok(),
39 _ => None,
40 }
41 }
42 }
43 )*};
44}
45
46ints!(i8 => "B", i16 => "S", u16 => "C", i32 => "I", i64 => "J");
47
48macro_rules! floats {
49 ($($t:ty => $desc:literal),* $(,)?) => {$(
50 impl Java for $t {
51 fn desc() -> String {
52 $desc.to_owned()
53 }
54 fn to_value(&self) -> Value {
55 Value::Float(f64::from(*self))
56 }
57 fn from_value(v: Value) -> Option<Self> {
58 match v {
59 Value::Float(f) => Some(f as $t),
61 Value::Int(n) => Some(n as $t),
62 _ => None,
63 }
64 }
65 }
66 )*};
67}
68
69floats!(f32 => "F", f64 => "D");
70
71impl Java for bool {
72 fn desc() -> String {
73 "Z".to_owned()
74 }
75 fn to_value(&self) -> Value {
76 Value::Bool(*self)
77 }
78 fn from_value(v: Value) -> Option<Self> {
79 match v {
80 Value::Bool(b) => Some(b),
81 _ => None,
82 }
83 }
84}
85
86impl Java for String {
87 fn desc() -> String {
88 STRING.to_owned()
89 }
90 fn to_value(&self) -> Value {
91 Value::Str(self.clone())
92 }
93 fn from_value(v: Value) -> Option<Self> {
94 match v {
95 Value::Str(s) => Some(s),
96 _ => None,
97 }
98 }
99}
100
101pub(super) fn class_desc(class: &str) -> String {
103 format!("L{};", class.replace('.', "/"))
104}
105
106impl<T: Nanite> Java for T {
107 fn desc() -> String {
108 class_desc(T::CLASS)
109 }
110 fn to_value(&self) -> Value {
111 self.handle().to_value()
112 }
113 fn from_value(v: Value) -> Option<Self> {
114 Handle::from_value(v).map(T::from_handle)
115 }
116}
117
118macro_rules! replies {
120 ($($t:ty),* $(,)?) => {$(
121 impl Reply for $t {
122 fn desc() -> String {
123 <$t as Java>::desc()
124 }
125 fn from_reply(v: Option<Value>) -> Self {
126 v.and_then(<$t as Java>::from_value).unwrap_or_default()
127 }
128 }
129 )*};
130}
131
132replies!(i8, i16, u16, i32, i64, f32, f64, bool, String);
133
134impl Reply for () {
135 fn desc() -> String {
136 VOID.to_owned()
137 }
138 fn from_reply(_: Option<Value>) -> Self {}
139}
140
141impl<T: Java> Reply for Option<T> {
143 fn desc() -> String {
144 T::desc()
145 }
146 fn from_reply(v: Option<Value>) -> Self {
147 v.and_then(T::from_value)
148 }
149}
150
151impl<T: Java> Java for Option<T> {
153 fn desc() -> String {
154 T::desc()
155 }
156 fn to_value(&self) -> Value {
157 self.as_ref().map_or(Value::Null, Java::to_value)
158 }
159 fn from_value(v: Value) -> Option<Self> {
160 Some(T::from_value(v))
161 }
162}