toad_jni/java/lang/
throwable.rs1use java::NoUpcast;
2
3use crate::java::{self, Nullable, Object};
4
5pub struct StackTraceElement(java::lang::Object);
7java::object_newtype!(StackTraceElement);
8impl java::Class for StackTraceElement {
9 const PATH: &'static str = "java/lang/StackTraceElement";
10}
11
12pub struct Throwable(java::lang::Object);
14
15java::object_newtype!(Throwable);
16impl java::Class for Throwable {
17 const PATH: &'static str = "java/lang/Throwable";
18}
19
20impl Throwable {
21 pub fn stack_trace(&self, e: &mut java::Env) -> Vec<StackTraceElement> {
23 java::Method::<Self, fn() -> Vec<StackTraceElement>>::new("getStackTrace").invoke(e, self)
24 }
25
26 pub fn cause(&self, e: &mut java::Env) -> Option<Throwable> {
28 java::Method::<Self, fn() -> Nullable<Throwable>>::new("getCause").invoke(e, self)
29 .into_option(e)
30 }
31
32 pub fn cause_iter(&self, e: &mut java::Env) -> impl Iterator<Item = Throwable> {
34 struct Iter(Throwable);
35 impl Iterator for Iter {
36 type Item = Throwable;
37
38 fn next(&mut self) -> Option<Self::Item> {
39 let mut e = java::env();
40 let e = &mut e;
41 let c = self.0.cause(e);
42 if let Some(c) = c.as_ref() {
43 self.0 = c.downcast_ref(e).upcast_to(e);
44 }
45 c
46 }
47 }
48
49 Iter(self.downcast_ref(e).upcast_to(e))
50 }
51}
52
53impl core::fmt::Debug for Throwable {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 let mut e = java::env();
56 let e = &mut e;
57 let traces = self.stack_trace(e);
58 let traces = traces.into_iter()
59 .map(|o| o.downcast(e).to_string(e))
60 .collect::<Vec<_>>();
61 write!(f, "{}\n", self.downcast_ref(e).to_string(e))?;
62 self.cause_iter(e)
63 .try_for_each(|cause| write!(f, " {}\n", cause.downcast_ref(e).to_string(e)))?;
64 write!(f, "\nstacktrace:\n{:#?}", traces)?;
65
66 Ok(())
67 }
68}
69
70#[cfg(test)]
71mod tests {
72 use crate::java::io::IOException;
73
74 #[test]
75 fn dbg() {
76 let mut e = crate::test::init();
77 let e = &mut e;
78 let baz = IOException::new(e, "baz").to_throwable(e);
79 let bar = IOException::new_caused_by(e, "bar", baz).to_throwable(e);
80 let foo = IOException::new_caused_by(e, "foo", bar).to_throwable(e);
81
82 assert_eq!(
83 format!("{:?}", foo),
84 format!(
85 r#"
86java.io.IOException: foo
87 java.io.IOException: bar
88 java.io.IOException: baz
89
90stacktrace:
91{:#?}"#,
92 Vec::<String>::new()
93 ).trim_start()
94 );
95 }
96}