use crate::{
encodings::{self, bytes_to_string},
Error, Object, Result, StringFormat,
};
pub fn text_string(text: &str) -> Object {
if text.is_ascii() {
return Object::String(text.into(), StringFormat::Literal);
}
Object::String(encodings::encode_utf16_be(text), StringFormat::Hexadecimal)
}
pub fn decode_text_string(obj: &Object) -> Result<String> {
let s = obj.as_str()?;
if s.starts_with(b"\xFE\xFF") {
String::from_utf16(
&s[2..]
.chunks(2)
.map(|c| {
if c.len() == 1 {
u16::from_be_bytes([c[0], 0])
} else {
u16::from_be_bytes(c.try_into().unwrap())
}
})
.collect::<Vec<u16>>(),
)
.map_err(|_| Error::TextStringDecode)
} else if s.starts_with(b"\xEF\xBB\xBF") {
String::from_utf8(s.to_vec()).map_err(|_| Error::TextStringDecode)
} else {
Ok(bytes_to_string(&encodings::PDF_DOC_ENCODING, s))
}
}
#[cfg(test)]
mod test {
use crate::{
common_data_structures::decode_text_string, encodings, parser::ParserInput, text_string, writer::Writer,
Object, StringFormat,
};
#[test]
fn spec_example1_encode() {
let input = "text‰";
let text_string = encodings::string_to_bytes(&encodings::PDF_DOC_ENCODING, input);
let dict = Object::Dictionary(dictionary!(
"Key" => Object::String(text_string, StringFormat::Literal),
));
let mut actual = vec![];
Writer::write_object(&mut actual, &dict).unwrap();
let expected = b"<</Key(text\x8B)>>";
assert_eq!(actual.as_slice(), expected);
}
#[test]
fn spec_example1_decode() {
let input = b"<</Key(text\\213)>>";
let dict = crate::parser::direct_object(ParserInput::new_extra(input, "")).unwrap();
let dict = dict.as_dict().unwrap();
let actual = decode_text_string(dict.get(b"Key").unwrap()).unwrap();
let expected = "text‰";
assert_eq!(&actual, expected);
}
#[test]
fn spec_example2_encode() {
let input = "тест";
let dict = Object::Dictionary(dictionary!(
"Key" => text_string(input),
));
let mut actual = vec![];
Writer::write_object(&mut actual, &dict).unwrap();
let expected = b"<</Key<FEFF0442043504410442>>>";
assert_eq!(actual.as_slice(), expected);
}
#[test]
fn spec_example2_decode() {
let input = b"<</Key<FEFF0442043504410442>>>";
let dict = crate::parser::direct_object(ParserInput::new_extra(input, "")).unwrap();
let dict = dict.as_dict().unwrap();
let actual = decode_text_string(dict.get(b"Key").unwrap()).unwrap();
let expected = "тест";
assert_eq!(&actual, expected);
}
}