1use std::fmt::Display;
2
3use jni::objects::{GlobalRef, JObject};
4
5use super::{Class, NoUpcast};
6use crate::java;
7
8#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
22pub struct Signature {
23 bytes: [u8; 256],
24 len: usize,
25 finished: bool,
26}
27
28impl Signature {
29 const CLASS_PATH_OPEN: Self = Self::empty().push_str("L");
30 const CLASS_PATH_CLOSE: Self = Self::empty().push_str(";");
31 const ARRAY_OF: Self = Self::empty().push_str("[");
32 const ARGS_OPEN: Self = Self::empty().push_str("(");
33 const ARGS_CLOSE: Self = Self::empty().push_str(")");
34
35 pub const fn of<T>() -> Self
37 where T: Type
38 {
39 T::SIG
40 }
41
42 pub fn return_type(self) -> jni::signature::ReturnType {
44 use jni::signature::Primitive::*;
45 use jni::signature::ReturnType::*;
46
47 let ret = self.as_str();
48 let ret = ret.split(')')
49 .nth(1)
50 .unwrap_or_else(|| panic!("{:?} is not a function signature", self));
51
52 if ret.starts_with(Self::ARRAY_OF.as_str()) {
53 Array
54 } else if ret.starts_with(Self::CLASS_PATH_OPEN.as_str()) {
55 Object
56 } else {
57 Primitive(match Signature::empty().push_str(ret) {
58 | <()>::SIG => Void,
59 | bool::SIG => Boolean,
60 | u16::SIG => Char,
61 | i8::SIG => Byte,
62 | i16::SIG => Short,
63 | i32::SIG => Int,
64 | i64::SIG => Long,
65 | f32::SIG => Float,
66 | f64::SIG => Double,
67 | _ => unreachable!(),
68 })
69 }
70 }
71
72 const fn empty() -> Self {
73 Self { bytes: [0; 256],
74 len: 0,
75 finished: false }
76 }
77
78 pub(crate) const fn function() -> Self {
79 Self::empty().concat(Self::ARGS_OPEN)
80 }
81
82 const fn array_of(t: Self) -> Self {
83 Self::empty().concat(Self::ARRAY_OF).concat(t)
84 }
85
86 const fn class(path: &'static str) -> Self {
87 Self::empty().concat(Self::CLASS_PATH_OPEN)
88 .push_str(path)
89 .concat(Self::CLASS_PATH_CLOSE)
90 }
91
92 const fn next(&self) -> usize {
93 self.len
94 }
95
96 pub(crate) const fn concat(mut self, other: Signature) -> Self {
97 let mut i = 0;
98 loop {
99 if i == other.len {
100 break;
101 }
102 self = self.push_byte(other.bytes[i]);
103 i += 1;
104 }
105
106 self
107 }
108
109 const fn push_byte(mut self, b: u8) -> Self {
110 if self.finished {
111 panic!("cannot modify Sig after invoking .ret()")
112 }
113 let n = self.next();
114 self.bytes[n] = b;
115 self.len += 1;
116 self
117 }
118
119 const fn push_str(mut self, s: &str) -> Self {
120 let mut i = 0;
121 loop {
122 if i == s.len() {
123 break;
124 }
125
126 let b = s.as_bytes()[i];
127 self = self.push_byte(b);
128
129 i += 1;
130 }
131
132 self
133 }
134
135 pub(crate) const fn ret(mut self, ret: Self) -> Self {
136 self = self.concat(Self::ARGS_CLOSE).concat(ret);
137 self.finished = true;
138 self
139 }
140
141 pub fn as_str(&self) -> &str {
143 match core::str::from_utf8(&self.bytes[0..self.len]) {
144 | Ok(s) => s,
145 | _ => unreachable!(),
146 }
147 }
148}
149
150impl Display for Signature {
151 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
152 write!(f, "{}", self.as_str())
153 }
154}
155
156impl AsRef<str> for Signature {
157 fn as_ref(&self) -> &str {
158 self.as_str()
159 }
160}
161
162mod type_sealed {
163 use jni::objects::GlobalRef;
164
165 use crate::java;
166
167 #[allow(unreachable_pub)]
168 pub trait TypeSealed {}
169 impl<T> TypeSealed for T where T: java::Class {}
170 impl<T> TypeSealed for Result<T, java::lang::Throwable> where T: java::Type {}
171 impl<T> TypeSealed for Vec<T> where T: java::Type {}
172 impl<R> TypeSealed for fn() -> R where R: java::Type {}
173 impl<A, R> TypeSealed for fn(A) -> R where R: java::Type {}
174 impl<A, B, R> TypeSealed for fn(A, B) -> R where R: java::Type {}
175 impl<A, B, C, R> TypeSealed for fn(A, B, C) -> R where R: java::Type {}
176 impl<A, B, C, D, R> TypeSealed for fn(A, B, C, D) -> R where R: java::Type {}
177 impl<A, B, C, D, E, R> TypeSealed for fn(A, B, C, D, E) -> R where R: java::Type {}
178 impl TypeSealed for GlobalRef {}
179 impl TypeSealed for () {}
180 impl TypeSealed for u16 {}
181 impl TypeSealed for bool {}
182 impl TypeSealed for i8 {}
183 impl TypeSealed for i16 {}
184 impl TypeSealed for i32 {}
185 impl TypeSealed for i64 {}
186 impl TypeSealed for f32 {}
187 impl TypeSealed for f64 {}
188}
189
190pub trait Type: type_sealed::TypeSealed {
216 const SIG: Signature;
218
219 fn is_type_of(e: &mut java::Env, o: &JObject) -> bool {
221 e.is_instance_of(o, Self::SIG).unwrap()
222 }
223
224 fn jni() -> jni::signature::JavaType;
226}
227
228impl<T> Type for T where T: java::Class
229{
230 const SIG: Signature = Signature::class(T::PATH);
231 fn jni() -> jni::signature::JavaType {
232 jni::signature::JavaType::Object(T::PATH.into())
233 }
234}
235
236impl<T> Type for Result<T, java::lang::Throwable> where T: java::Class
237{
238 const SIG: Signature = Signature::class(T::PATH);
239 fn jni() -> jni::signature::JavaType {
240 jni::signature::JavaType::Object(T::PATH.into())
241 }
242}
243
244impl Type for GlobalRef {
245 const SIG: Signature = java::lang::Object::SIG;
246 fn jni() -> jni::signature::JavaType {
247 jni::signature::JavaType::Object(java::lang::Object::PATH.into())
248 }
249}
250
251impl Type for () {
252 const SIG: Signature = Signature::empty().push_str("V");
253 fn jni() -> jni::signature::JavaType {
254 jni::signature::JavaType::Primitive(jni::signature::Primitive::Void)
255 }
256}
257
258impl Type for u16 {
259 const SIG: Signature = Signature::empty().push_str("C");
260 fn jni() -> jni::signature::JavaType {
261 jni::signature::JavaType::Primitive(jni::signature::Primitive::Char)
262 }
263}
264
265impl Type for i8 {
266 const SIG: Signature = Signature::empty().push_str("B");
267 fn jni() -> jni::signature::JavaType {
268 jni::signature::JavaType::Primitive(jni::signature::Primitive::Byte)
269 }
270}
271
272impl Type for i16 {
273 const SIG: Signature = Signature::empty().push_str("S");
274 fn jni() -> jni::signature::JavaType {
275 jni::signature::JavaType::Primitive(jni::signature::Primitive::Short)
276 }
277}
278
279impl Type for i32 {
280 const SIG: Signature = Signature::empty().push_str("I");
281 fn jni() -> jni::signature::JavaType {
282 jni::signature::JavaType::Primitive(jni::signature::Primitive::Int)
283 }
284}
285
286impl Type for i64 {
287 const SIG: Signature = Signature::empty().push_str("J");
288 fn jni() -> jni::signature::JavaType {
289 jni::signature::JavaType::Primitive(jni::signature::Primitive::Long)
290 }
291}
292
293impl Type for f32 {
294 const SIG: Signature = Signature::empty().push_str("F");
295 fn jni() -> jni::signature::JavaType {
296 jni::signature::JavaType::Primitive(jni::signature::Primitive::Float)
297 }
298}
299
300impl Type for f64 {
301 const SIG: Signature = Signature::empty().push_str("D");
302 fn jni() -> jni::signature::JavaType {
303 jni::signature::JavaType::Primitive(jni::signature::Primitive::Double)
304 }
305}
306
307impl Type for bool {
308 const SIG: Signature = Signature::empty().push_str("Z");
309 fn jni() -> jni::signature::JavaType {
310 jni::signature::JavaType::Primitive(jni::signature::Primitive::Boolean)
311 }
312}
313
314impl<T> Type for Vec<T> where T: Type
315{
316 const SIG: Signature = Signature::array_of(T::SIG);
317 fn jni() -> jni::signature::JavaType {
318 jni::signature::JavaType::Array(Box::new(T::jni()))
319 }
320}
321
322impl<R> Type for fn() -> R where R: Type
323{
324 const SIG: Signature = Signature::function().ret(R::SIG);
325 fn jni() -> jni::signature::JavaType {
326 jni::signature::JavaType::Method(Box::new(jni::signature::TypeSignature { args: vec![], ret: Self::SIG.return_type() }))
327 }
328}
329
330impl<R, A> Type for fn(A) -> R
331 where R: Type,
332 A: Type
333{
334 const SIG: Signature = Signature::function().concat(A::SIG).ret(R::SIG);
335 fn jni() -> jni::signature::JavaType {
336 jni::signature::JavaType::Method(Box::new(jni::signature::TypeSignature { args: vec![A::jni()], ret: Self::SIG.return_type() }))
337 }
338}
339
340impl<R, A, B> Type for fn(A, B) -> R
341 where R: Type,
342 A: Type,
343 B: Type
344{
345 const SIG: Signature = Signature::function().concat(A::SIG)
346 .concat(B::SIG)
347 .ret(R::SIG);
348 fn jni() -> jni::signature::JavaType {
349 jni::signature::JavaType::Method(Box::new(jni::signature::TypeSignature { args: vec![A::jni(), B::jni()], ret: Self::SIG.return_type() }))
350 }
351}
352
353impl<R, A, B, C> Type for fn(A, B, C) -> R
354 where R: Type,
355 A: Type,
356 B: Type,
357 C: Type
358{
359 const SIG: Signature = Signature::function().concat(A::SIG)
360 .concat(B::SIG)
361 .concat(C::SIG)
362 .ret(R::SIG);
363 fn jni() -> jni::signature::JavaType {
364 jni::signature::JavaType::Method(Box::new(jni::signature::TypeSignature { args: vec![A::jni(), B::jni(), C::jni()], ret: Self::SIG.return_type() }))
365 }
366}
367
368impl<R, A, B, C, D> Type for fn(A, B, C, D) -> R
369 where R: Type,
370 A: Type,
371 B: Type,
372 C: Type,
373 D: Type
374{
375 const SIG: Signature = Signature::function().concat(A::SIG)
376 .concat(B::SIG)
377 .concat(C::SIG)
378 .concat(D::SIG)
379 .ret(R::SIG);
380 fn jni() -> jni::signature::JavaType {
381 jni::signature::JavaType::Method(Box::new(jni::signature::TypeSignature { args: vec![A::jni(), B::jni(), C::jni(), D::jni()], ret: Self::SIG.return_type() }))
382 }
383}
384
385impl<R, A, B, C, D, E> Type for fn(A, B, C, D, E) -> R
386 where R: Type,
387 A: Type,
388 B: Type,
389 C: Type,
390 D: Type,
391 E: Type
392{
393 const SIG: Signature = Signature::function().concat(A::SIG)
394 .concat(B::SIG)
395 .concat(C::SIG)
396 .concat(D::SIG)
397 .concat(E::SIG)
398 .ret(R::SIG);
399 fn jni() -> jni::signature::JavaType {
400 jni::signature::JavaType::Method(Box::new(jni::signature::TypeSignature { args: vec![A::jni(), B::jni(), C::jni(), D::jni(), E::jni()], ret: Self::SIG.return_type() }))
401 }
402}
403
404#[cfg(test)]
405pub mod test {
406 use crate::java::Signature;
407
408 #[test]
409 fn return_type() {
410 use jni::signature::Primitive::*;
411 use jni::signature::ReturnType::*;
412
413 assert_eq!(Signature::of::<fn()>().return_type(), Primitive(Void));
414 assert_eq!(Signature::of::<fn(String) -> String>().return_type(),
415 Object);
416 assert_eq!(Signature::of::<fn(String) -> Vec<String>>().return_type(),
417 Array);
418 assert_eq!(Signature::of::<fn() -> u16>().return_type(),
419 Primitive(Char));
420 assert_eq!(Signature::of::<fn() -> bool>().return_type(),
421 Primitive(Boolean));
422 assert_eq!(Signature::of::<fn() -> i8>().return_type(), Primitive(Byte));
423 assert_eq!(Signature::of::<fn() -> i16>().return_type(),
424 Primitive(Short));
425 assert_eq!(Signature::of::<fn() -> i32>().return_type(), Primitive(Int));
426 assert_eq!(Signature::of::<fn() -> i64>().return_type(),
427 Primitive(Long));
428 assert_eq!(Signature::of::<fn() -> f32>().return_type(),
429 Primitive(Float));
430 assert_eq!(Signature::of::<fn() -> f64>().return_type(),
431 Primitive(Double));
432 }
433}