1use crate::commands::{
5 command_sets, object_reference_commands, reference_type_commands, stack_frame_commands,
6};
7use crate::connection::JdwpConnection;
8use crate::protocol::{CommandPacket, JdwpResult};
9use crate::reader::{read_string, read_u64, read_u8, read_value_by_tag};
10use crate::types::{ClassId, FrameId, MethodId, ObjectId, ReferenceTypeId, ThreadId, Value, ValueData};
11use bytes::BufMut;
12
13const CLASS_TYPE_SUPERCLASS: u8 = 1;
15const CLASS_TYPE_INVOKE_METHOD: u8 = 3;
17const INVOKE_SINGLE_THREADED: i32 = 1;
19
20impl JdwpConnection {
21 pub async fn get_signature(&mut self, ref_type_id: ReferenceTypeId) -> JdwpResult<String> {
26 if let Some(hit) = self.types().signature(ref_type_id) {
29 return Ok(hit);
30 }
31 let packet = self.signature_request(ref_type_id);
32 let reply = self.send_command(packet).await?;
33 let sig = Self::decode_signature_reply(&reply)?;
34 self.types().put_signature(ref_type_id, &sig);
35 Ok(sig)
36 }
37
38 pub async fn read_signatures_independently(
49 &self,
50 ref_type_ids: &[ReferenceTypeId],
51 ) -> Vec<JdwpResult<String>> {
52 let mut wanted: Vec<ReferenceTypeId> = Vec::new();
55 for &id in ref_type_ids {
56 if self.types().signature(id).is_none() && !wanted.contains(&id) {
57 wanted.push(id);
58 }
59 }
60 if !wanted.is_empty() {
61 let packets = wanted.iter().map(|&id| self.signature_request(id)).collect();
62 for (&type_id, reply) in wanted.iter().zip(self.read_independently(packets).await) {
63 if let Ok(sig) = reply.and_then(|r| Self::decode_signature_reply(&r)) {
64 self.types().put_signature(type_id, &sig);
65 }
66 }
67 }
68 ref_type_ids
71 .iter()
72 .map(|&id| {
73 self.types().signature(id).ok_or_else(|| {
74 crate::protocol::JdwpError::Protocol(format!(
75 "the signature of type {id} could not be read"
76 ))
77 })
78 })
79 .collect()
80 }
81
82 fn signature_request(&self, ref_type_id: ReferenceTypeId) -> CommandPacket {
84 let id = self.next_id();
85 let mut packet =
86 CommandPacket::new(id, command_sets::REFERENCE_TYPE, reference_type_commands::SIGNATURE);
87 packet.data.put_u64(ref_type_id);
88 packet
89 }
90
91 fn decode_signature_reply(reply: &crate::protocol::ReplyPacket) -> JdwpResult<String> {
95 reply.check_error()?;
96 let mut data = reply.data();
97 read_string(&mut data)
98 }
99
100 pub async fn get_superclass(&mut self, class_id: ClassId) -> JdwpResult<Option<ClassId>> {
105 match self.types().superclass(class_id) {
106 crate::connection::CachedSuperclass::Root => return Ok(None),
107 crate::connection::CachedSuperclass::Parent(p) => return Ok(Some(p)),
108 crate::connection::CachedSuperclass::Unknown => {}
109 }
110 let id = self.next_id();
111 let mut packet = CommandPacket::new(id, command_sets::CLASS_TYPE, CLASS_TYPE_SUPERCLASS);
112 packet.data.put_u64(class_id);
113 let reply = self.send_command(packet).await?;
114 reply.check_error()?;
115 let mut data = reply.data();
116 let sc = read_u64(&mut data)?;
117 let parent = if sc == 0 { None } else { Some(sc) };
118 self.types().put_superclass(class_id, parent);
119 Ok(parent)
120 }
121
122 pub async fn get_this_object(&mut self, thread_id: ThreadId, frame_id: FrameId) -> JdwpResult<ObjectId> {
127 let id = self.next_id();
128 let mut packet = CommandPacket::new(id, command_sets::STACK_FRAME, stack_frame_commands::THIS_OBJECT);
129 packet.data.put_u64(thread_id);
130 packet.data.put_u64(frame_id);
131 let reply = self.send_command(packet).await?;
132 reply.check_error()?;
133 let mut data = reply.data();
134 let _tag = read_u8(&mut data)?;
135 read_u64(&mut data)
136 }
137
138 pub async fn invoke_method(
147 &mut self,
148 object_id: ObjectId,
149 thread_id: ThreadId,
150 class_id: ClassId,
151 method_id: MethodId,
152 args: Vec<Value>,
153 ) -> JdwpResult<(Value, ObjectId)> {
154 self.guard_mutation("an instance method invocation")?;
155 let id = self.next_id();
156 let mut packet =
157 CommandPacket::new(id, command_sets::OBJECT_REFERENCE, object_reference_commands::INVOKE_METHOD);
158 packet.data.put_u64(object_id);
159 packet.data.put_u64(thread_id);
160 packet.data.put_u64(class_id);
161 packet.data.put_u64(method_id);
162 packet.data.put_i32(i32::try_from(args.len()).unwrap_or(i32::MAX));
163 for a in &args {
164 write_tagged_value(&mut packet.data, a);
165 }
166 packet.data.put_i32(INVOKE_SINGLE_THREADED);
167
168 let reply = self.send_invoke(packet).await?;
170 reply.check_error()?;
171 read_invoke_reply(reply.data())
172 }
173
174 pub async fn invoke_static_method(
186 &mut self,
187 class_id: ClassId,
188 thread_id: ThreadId,
189 method_id: MethodId,
190 args: Vec<Value>,
191 ) -> JdwpResult<(Value, ObjectId)> {
192 self.guard_mutation("a static method invocation")?;
193 let id = self.next_id();
194 let mut packet = CommandPacket::new(id, command_sets::CLASS_TYPE, CLASS_TYPE_INVOKE_METHOD);
195 packet.data.put_u64(class_id);
196 packet.data.put_u64(thread_id);
197 packet.data.put_u64(method_id);
198 packet.data.put_i32(i32::try_from(args.len()).unwrap_or(i32::MAX));
199 for a in &args {
200 write_tagged_value(&mut packet.data, a);
201 }
202 packet.data.put_i32(INVOKE_SINGLE_THREADED);
203
204 let reply = self.send_invoke(packet).await?;
206 reply.check_error()?;
207 read_invoke_reply(reply.data())
208 }
209}
210
211fn read_invoke_reply(mut data: &[u8]) -> JdwpResult<(Value, ObjectId)> {
215 let ret_tag = read_u8(&mut data)?;
216 let ret = Value { tag: ret_tag, data: read_value_by_tag(ret_tag, &mut data)? };
217 let _exc_tag = read_u8(&mut data)?;
218 let exc_id = read_u64(&mut data)?;
219 Ok((ret, exc_id))
220}
221
222pub(crate) fn write_tagged_value<B: BufMut>(buf: &mut B, v: &Value) {
223 buf.put_u8(v.tag);
224 write_untagged_value(buf, v);
225}
226
227pub(crate) fn write_untagged_value<B: BufMut>(buf: &mut B, v: &Value) {
232 match &v.data {
233 ValueData::Byte(x) => buf.put_i8(*x),
234 ValueData::Char(x) => buf.put_u16(*x),
235 ValueData::Float(x) => buf.put_f32(*x),
236 ValueData::Double(x) => buf.put_f64(*x),
237 ValueData::Int(x) => buf.put_i32(*x),
238 ValueData::Long(x) => buf.put_i64(*x),
239 ValueData::Short(x) => buf.put_i16(*x),
240 ValueData::Boolean(x) => buf.put_u8(u8::from(*x)),
241 ValueData::Object(x) => buf.put_u64(*x),
242 ValueData::Void => {}
243 }
244}