Skip to content

Commit 9209351

Browse files
committed
Fix parsing of multibyte (encoded) values
1 parent 7659e20 commit 9209351

File tree

2 files changed

+117
-99
lines changed

2 files changed

+117
-99
lines changed

CHANGELOG.md

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,22 @@ CHANGELOG
44
main
55
----
66

7+
### Features
8+
9+
- Add support for arrow key scrolling
10+
- Show historic inline values
711
- Introduce eval feature
12+
13+
### Improvements
14+
815
- Improve scrolling performance on large files and contexts
9-
- Add support for arrow key scrolling
16+
17+
### Bug fixes
18+
1019
- Fix position of closing braces in context view
11-
- Show historic inline values
1220
- Do not show "undefined" variables
1321
- Ensure context depth is in range of 1-9
22+
- Fix display of multibyte values #27
1423

1524
0.1.1
1625
-----

src/dbgp/client.rs

Lines changed: 106 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ use anyhow::Result;
22
use base64::engine::general_purpose;
33
use base64::Engine;
44
use core::str;
5-
use std::fmt::Display;
65
use log::debug;
6+
use std::fmt::Display;
77
use tokio::io::AsyncBufReadExt;
88
use tokio::io::AsyncWriteExt;
99
use tokio::io::BufReader;
@@ -44,8 +44,7 @@ pub struct DbgpError {
4444
pub struct ContextGetResponse {
4545
pub properties: Properties,
4646
}
47-
impl ContextGetResponse {
48-
}
47+
impl ContextGetResponse {}
4948
#[derive(Debug, Clone, PartialEq, Default)]
5049
pub struct Properties {
5150
pub properties: Vec<Property>,
@@ -55,7 +54,7 @@ impl Properties {
5554
self.properties.is_empty()
5655
}
5756
pub fn none() -> Self {
58-
Self{properties:vec![]}
57+
Self { properties: vec![] }
5958
}
6059
pub fn defined_properties(&self) -> Vec<&Property> {
6160
let mut props = vec![];
@@ -71,14 +70,14 @@ impl Properties {
7170
pub(crate) fn get(&self, name: &str) -> Option<&Property> {
7271
for property in self.defined_properties() {
7372
if property.name == name {
74-
return Some(property)
73+
return Some(property);
7574
}
7675
}
7776
None
7877
}
7978

8079
pub fn from_properties(vec: Vec<Property>) -> Properties {
81-
Self{properties:vec}
80+
Self { properties: vec }
8281
}
8382
}
8483

@@ -286,7 +285,10 @@ impl DbgpClient {
286285
}
287286

288287
pub(crate) async fn context_get(&mut self, depth: u16) -> Result<ContextGetResponse> {
289-
match self.command("context_get", &mut ["-d", format!("{}", depth).as_str()]).await? {
288+
match self
289+
.command("context_get", &mut ["-d", format!("{}", depth).as_str()])
290+
.await?
291+
{
290292
Message::Response(r) => match r.command {
291293
CommandResponse::ContextGet(s) => Ok(s),
292294
_ => anyhow::bail!("Unexpected response"),
@@ -297,7 +299,13 @@ impl DbgpClient {
297299

298300
pub(crate) async fn eval(&mut self, expression: String, depth: u16) -> Result<EvalResponse> {
299301
let base64 = general_purpose::STANDARD.encode(expression.as_bytes());
300-
match self.command("eval", &mut ["-d", format!("{}", depth).as_str(), "--", &base64]).await? {
302+
match self
303+
.command(
304+
"eval",
305+
&mut ["-d", format!("{}", depth).as_str(), "--", &base64],
306+
)
307+
.await?
308+
{
301309
Message::Response(r) => match r.command {
302310
CommandResponse::Eval(s) => Ok(s),
303311
_ => anyhow::bail!("Unexpected response"),
@@ -370,7 +378,8 @@ impl DbgpClient {
370378
let bytes = [cmd_str.trim_end(), "\0"].concat();
371379
self.tid += 1;
372380
match self.stream.as_mut() {
373-
Some(stream) => stream.write(bytes.as_bytes())
381+
Some(stream) => stream
382+
.write(bytes.as_bytes())
374383
.await
375384
.map_err(anyhow::Error::from),
376385
None => Err(anyhow::anyhow!("Stream was closed")),
@@ -439,63 +448,63 @@ fn parse_xml(xml: &str) -> Result<Message, anyhow::Error> {
439448
}
440449
fn parse_source(element: &Element) -> Result<String, anyhow::Error> {
441450
match element.children.first() {
442-
Some(XMLNode::CData(e)) => {
443-
Ok(String::from_utf8(general_purpose::STANDARD.decode(e)?)?)
444-
}
451+
Some(XMLNode::CData(e)) => Ok(String::from_utf8(general_purpose::STANDARD.decode(e)?)?),
445452
_ => anyhow::bail!("Expected CDATA"),
446453
}
447454
}
448455

449-
450456
fn parse_context_get(element: &mut Element) -> Result<ContextGetResponse, anyhow::Error> {
451-
Ok(ContextGetResponse { properties: Properties::from_properties(parse_properties(element)?)})
457+
Ok(ContextGetResponse {
458+
properties: Properties::from_properties(parse_properties(element)?),
459+
})
452460
}
453461

454462
fn parse_eval(element: &mut Element) -> Result<EvalResponse, anyhow::Error> {
455-
456463
let error = if let Some(mut error_el) = element.take_child("error") {
457-
let code = error_el.attributes.get("code").map_or("".to_string(), |v|v.to_string());
464+
let code = error_el
465+
.attributes
466+
.get("code")
467+
.map_or("".to_string(), |v| v.to_string());
458468
let message = match error_el.take_child("message") {
459469
Some(m) => match m.children.first() {
460-
Some(XMLNode::CData(e)) => {
461-
e.to_string()
462-
},
470+
Some(XMLNode::CData(e)) => e.to_string(),
463471
_ => String::new(),
464472
},
465-
_ => "".to_string()
473+
_ => "".to_string(),
466474
};
467-
468-
Some(DbgpError{message, code: code.to_string()})
475+
476+
Some(DbgpError {
477+
message,
478+
code: code.to_string(),
479+
})
469480
} else {
470481
None
471482
};
472483

473-
Ok(EvalResponse { success: true, properties: Properties::from_properties(parse_properties(element)?), error})
484+
Ok(EvalResponse {
485+
success: true,
486+
properties: Properties::from_properties(parse_properties(element)?),
487+
error,
488+
})
474489
}
475490

476491
fn parse_properties(element: &mut Element) -> Result<Vec<Property>, anyhow::Error> {
477492
let mut properties: Vec<Property> = vec![];
478493
while let Some(mut child) = element.take_child("property") {
479494
let encoding = child.attributes.get("encoding").map(|s| s.to_string());
480495
let p = Property {
481-
name: match child
482-
.attributes
483-
.get("name") {
484-
Some(name) => name.to_string(),
485-
None => decode_element(child.get_child("name")).unwrap_or("".to_string())
486-
},
487-
fullname: match child
488-
.attributes
489-
.get("fullname") {
490-
Some(name) => name.to_string(),
491-
None => decode_element(child.get_child("fullname")).unwrap_or("".to_string())
492-
},
493-
classname: match child
494-
.attributes
495-
.get("classname") {
496-
Some(name) => Some(name.to_string()),
497-
None => decode_element(child.get_child("classname"))
498-
},
496+
name: match child.attributes.get("name") {
497+
Some(name) => name.to_string(),
498+
None => decode_element(child.get_child("name")).unwrap_or("".to_string()),
499+
},
500+
fullname: match child.attributes.get("fullname") {
501+
Some(name) => name.to_string(),
502+
None => decode_element(child.get_child("fullname")).unwrap_or("".to_string()),
503+
},
504+
classname: match child.attributes.get("classname") {
505+
Some(name) => Some(name.to_string()),
506+
None => decode_element(child.get_child("classname")),
507+
},
499508
page: child
500509
.attributes
501510
.get("page")
@@ -519,7 +528,10 @@ fn parse_properties(element: &mut Element) -> Result<Vec<Property>, anyhow::Erro
519528
address: child.attributes.get("address").map(|name| name.to_string()),
520529
encoding: encoding.clone(),
521530
children: Properties::from_properties(parse_properties(&mut child)?),
522-
value: decode_element(Some(&child)),
531+
value: match child.get_child("value") {
532+
Some(v) => decode_element(Some(v)),
533+
None => decode_element(Some(&child)),
534+
}
523535
};
524536
properties.push(p);
525537
}
@@ -530,13 +542,13 @@ fn decode_element(element: Option<&Element>) -> Option<String> {
530542
match element {
531543
Some(e) => {
532544
let encoding = e.attributes.get("encoding");
533-
match e.children.first() {
545+
match e.children.first() {
534546
Some(XMLNode::CData(cdata)) => match encoding {
535547
Some(encoding) => match encoding.as_str() {
536-
"base64" => {
537-
Some(String::from_utf8(general_purpose::STANDARD.decode(cdata).unwrap())
538-
.unwrap())
539-
}
548+
"base64" => Some(
549+
String::from_utf8(general_purpose::STANDARD.decode(cdata).unwrap())
550+
.unwrap(),
551+
),
540552
_ => Some(cdata.to_string()),
541553
},
542554
_ => Some(cdata.to_string()),
@@ -706,23 +718,21 @@ function call_function(string $hello) {
706718
let expected = EvalResponse {
707719
success: true,
708720
error: None,
709-
properties: Properties::from_properties(vec![
710-
Property {
711-
name: "".to_string(),
712-
fullname: "".to_string(),
713-
classname: None,
714-
page: None,
715-
pagesize: None,
716-
property_type: PropertyType::Int,
717-
facet: None,
718-
size: None,
719-
children: Properties::none(),
720-
key: None,
721-
address: None,
722-
encoding: None,
723-
value: Some(2.to_string()),
724-
},
725-
]),
721+
properties: Properties::from_properties(vec![Property {
722+
name: "".to_string(),
723+
fullname: "".to_string(),
724+
classname: None,
725+
page: None,
726+
pagesize: None,
727+
property_type: PropertyType::Int,
728+
facet: None,
729+
size: None,
730+
children: Properties::none(),
731+
key: None,
732+
address: None,
733+
encoding: None,
734+
value: Some(2.to_string()),
735+
}]),
726736
};
727737
assert_eq!(expected, response)
728738
}
@@ -749,8 +759,9 @@ function call_function(string $hello) {
749759
let expected = EvalResponse {
750760
success: true,
751761
error: Some(DbgpError {
752-
message: "error evaluating code: Undefined constant \"asda\"".to_string(),
753-
code: "206".to_string()
762+
message: "error evaluating code: Undefined constant \"asda\""
763+
.to_string(),
764+
code: "206".to_string(),
754765
}),
755766
properties: Properties::none(),
756767
};
@@ -901,7 +912,9 @@ function call_function(string $hello) {
901912
key: None,
902913
address: None,
903914
encoding: None,
904-
value: Some("resource id='18' type='stream'".to_string()),
915+
value: Some(
916+
"resource id='18' type='stream'".to_string(),
917+
),
905918
},
906919
]),
907920
key: None,
@@ -925,7 +938,7 @@ function call_function(string $hello) {
925938
value: None,
926939
},
927940
]),
928-
};
941+
};
929942
assert_eq!(expected, response)
930943
}
931944
_ => panic!("Could not parse context_get"),
@@ -951,48 +964,44 @@ function call_function(string $hello) {
951964
</property>
952965
</property>
953966
</response>
954-
"#
967+
"#,
955968
)?;
956969

957970
match result {
958971
Message::Response(r) => {
959972
match r.command {
960973
CommandResponse::ContextGet(response) => {
961974
let expected = ContextGetResponse {
962-
properties: Properties::from_properties(vec![
963-
Property {
964-
name: "$ar😸ray".to_string(),
965-
fullname: "$ar😸ray".to_string(),
975+
properties: Properties::from_properties(vec![Property {
976+
name: "$ar😸ray".to_string(),
977+
fullname: "$ar😸ray".to_string(),
978+
classname: None,
979+
page: Some(0),
980+
pagesize: Some(32),
981+
property_type: PropertyType::Array,
982+
facet: None,
983+
size: None,
984+
children: Properties::from_properties(vec![Property {
985+
name: "int".to_string(),
986+
fullname: "$ar😸ray[\"int\"]".to_string(),
966987
classname: None,
967-
page: Some(0),
968-
pagesize: Some(32),
969-
property_type: PropertyType::Array,
988+
page: None,
989+
pagesize: None,
990+
property_type: PropertyType::Int,
970991
facet: None,
971992
size: None,
972-
children: Properties::from_properties(vec![
973-
Property {
974-
name: "int".to_string(),
975-
fullname: "$ar😸ray[\"int\"]".to_string(),
976-
classname: None,
977-
page: None,
978-
pagesize: None,
979-
property_type: PropertyType::Int,
980-
facet: None,
981-
size: None,
982-
children: Properties::none(),
983-
key: None,
984-
address: None,
985-
encoding: None,
986-
value: Some("1".to_string()),
987-
},
988-
]),
993+
children: Properties::none(),
989994
key: None,
990995
address: None,
991996
encoding: None,
992-
value: None,
993-
},
994-
]),
995-
};
997+
value: Some("123".to_string()),
998+
}]),
999+
key: None,
1000+
address: None,
1001+
encoding: None,
1002+
value: None,
1003+
}]),
1004+
};
9961005
assert_eq!(expected, response)
9971006
}
9981007
_ => panic!("Could not parse context_get"),

0 commit comments

Comments
 (0)