rust/json: only output printable characters

Rust strings are UTF8 and we cannot yet rely on jansson
having json_stringn on all supported OS distributions yet
so sanitize strings to ascii before printing.

Also add set_string_from_bytes which is like set_string, but
accepts a byte array as input.
pull/2790/head
Jason Ish 7 years ago
parent becf1a2dfe
commit 6dbc5be4be

@ -68,11 +68,19 @@ impl Json {
}
}
pub fn set_string_from_bytes(&self, key: &str, val: &[u8]) {
unsafe {
json_object_set_new(self.js,
CString::new(key).unwrap().as_ptr(),
json_string(to_cstring(val).as_ptr()));
}
}
pub fn set_string(&self, key: &str, val: &str) {
unsafe{
unsafe {
json_object_set_new(self.js,
CString::new(key).unwrap().as_ptr(),
json_string(CString::new(val).unwrap().as_ptr()));
json_string(to_cstring(val.as_bytes()).as_ptr()));
}
}
@ -98,3 +106,43 @@ impl Json {
}
}
}
/// Convert an array of bytes into an ascii printable string replacing
/// non-printable characters (including NULL) with hex value.
///
/// Newer versions of Jansson have a json_stringn that will allow us
/// to create a string out of a byte array of unicode compliant bytes,
/// but until we can use it across all platforms this is probably the
/// best we can do.
fn to_cstring(val: &[u8]) -> CString {
let mut safe = Vec::with_capacity(val.len());
for c in val {
if *c == 0 || *c > 0x7f {
safe.extend(format!("\\x{:02x}", *c).as_bytes());
} else {
safe.push(*c);
}
}
match CString::new(safe) {
Ok(cstr) => cstr,
_ => {
CString::new("<failed to encode string>").unwrap()
}
}
}
#[cfg(test)]
mod tests {
use json::to_cstring;
#[test]
fn test_to_string() {
assert_eq!("A\\x00A",
to_cstring(&[0x41, 0x00, 0x41]).into_string().unwrap());
assert_eq!("", to_cstring(&[]).into_string().unwrap());
assert_eq!("\\x80\\xf1\\xf2\\xf3",
to_cstring(&[0x80, 0xf1, 0xf2, 0xf3]).into_string().unwrap());
}
}

Loading…
Cancel
Save