Merge pull request #475 from dotCooCoo/fix/hayro-syntax-debug-closing-brace

hayro-syntax: tests check that valid entries survive an unreadable value, and Debug prints the closing brace
This commit is contained in:
Dylan M. Taylor
2026-11-02 21:57:54 -05:00
committed by GitHub
4 changed files with 53 additions and 10 deletions
+2
View File
@@ -113,6 +113,8 @@ Raw array iteration now ends safely if validation and object parsing disagree;
standalone sign tokens retain the reader's zero tolerance.
`Dict::entries` and a dictionary's `Debug` output skip an entry whose value does not parse,
as in [Hayro #1501](https://github.com/LaurenzV/hayro/pull/1501).
The `Debug` output of an array ends with its closing bracket, and that of a dictionary
with entries ends with its closing brace; an empty dictionary prints as `Dict`.
Byte transfer-function samples use rounded 8-bit values; failed or non-finite evaluations
leave the sample unchanged. Historical source hashes remain in each `SOURCE.json`,
alongside local hashes and the compatibility reference.
+4 -3
View File
@@ -212,7 +212,7 @@
"path": "src/object/array.rs",
"source_sha256": "6fbddf05724848db2389068a0504cff6b0783e35baa58e64bf2a31d48a1042ea",
"source_git_blob": "d39230f7dbf114dd202a16b21f7a6bb70be5ead3",
"sha256": "4537ab5cc06383e8b1e0dc97ae9fa1ee2869201615a37dea26bd0665006b2dd0"
"sha256": "8d5704b638f5198ec74604a3fd88a32dee553b6dc2a7010e746ef5e459759ed6"
},
{
"path": "src/object/bool.rs",
@@ -230,7 +230,7 @@
"path": "src/object/dict.rs",
"source_sha256": "bcfefabe931614b79ea54940d02fce534eb2363f1b75a03d6428fd7a04c57981",
"source_git_blob": "1e016b567e8ec17801fa8282c47f653092839cb5",
"sha256": "dac4329027aacb68c937fb2aa4b839960e0a94b6af40c4176b614ffa48157933"
"sha256": "b5699e0774bbb4dfd1ad8c6fa713274c854f10d8afcc8cbe5544bdda79b59bde"
},
{
"path": "src/object/indirect.rs",
@@ -371,6 +371,7 @@
"local_safety_repairs": [
"Match existing standalone-plus-as-zero tolerance in number parsing while retaining regular-character terminator rejection and numeric overflow guards.",
"End raw array iteration on object parse failure instead of panicking when validation and parsing differ.",
"Skip a dictionary entry whose value does not parse in Dict::entries and Dict's Debug output instead of panicking, as in LaurenzV/hayro#1501 (23a8e290d4195ab31f737c12a1b079c114cdd13c)."
"Skip a dictionary entry whose value does not parse in Dict::entries and Dict's Debug output instead of panicking, as in LaurenzV/hayro#1501 (23a8e290d4195ab31f737c12a1b079c114cdd13c).",
"End Dict and Array Debug output with finish(), as upstream does, so an array's closing bracket and a non-empty dictionary's closing brace are printed (an empty dictionary prints as Dict)."
]
}
+21 -2
View File
@@ -62,7 +62,7 @@ impl Debug for Array<'_> {
debug_list.entry(&i);
});
Ok(())
debug_list.finish()
}
}
@@ -443,6 +443,25 @@ mod tests {
#[test]
fn array_with_unreadable_item() {
let _ = array_ref_impl(b"[true /#zz false]");
for bytes in [
b"[true false /#zz true]".as_slice(),
b"[true false 12-.5 true]",
] {
let values = array_ref_impl(bytes).unwrap();
assert_eq!(values.len(), 2);
assert!(matches!(values[0], MaybeRef::NotRef(Object::Boolean(true))));
assert!(matches!(
values[1],
MaybeRef::NotRef(Object::Boolean(false))
));
let array = Reader::new(bytes)
.read_with_context::<Array<'_>>(&ReaderContext::new(XRef::dummy(), false))
.unwrap();
assert_eq!(
alloc::format!("{array:?}"),
"[Boolean(true), Boolean(false)]"
);
}
}
}
+26 -5
View File
@@ -160,7 +160,7 @@ impl Debug for Dict<'_> {
for (key, value) in self.entries() {
debug_struct.field(&format!("{:?}", key.as_str()), &value);
}
Ok(())
debug_struct.finish()
}
}
@@ -1258,7 +1258,7 @@ mod tests {
use crate::object::dict::keys::{COLORSPACE, EXT_G_STATE, FONT, PROC_SET};
use crate::object::dict::{Dict, InlineImageDict};
use crate::object::string;
use crate::object::{FromBytes, Name, ObjRef};
use crate::object::{FromBytes, MaybeRef, Name, ObjRef, Object};
use crate::reader::Reader;
use crate::reader::{ReaderContext, ReaderExt};
@@ -1404,8 +1404,29 @@ mod tests {
#[test]
fn dict_with_unreadable_value() {
let dict = Dict::from_bytes(b"<< /A /#zz /B true >>").unwrap();
let _ = dict.entries().count();
let _ = alloc::format!("{dict:?}");
for bytes in [
b"<< /A false /B /#zz /C true >>".as_slice(),
b"<< /A false /B 12-.5 /C true >>",
b"<< /A false /B << /Length 3 >> stream /C true >>",
] {
let dict = Dict::from_bytes(bytes).unwrap();
assert_eq!(dict.keys().count(), 3);
let entries = dict.entries().collect::<Vec<_>>();
assert_eq!(entries.len(), 2);
assert_eq!(entries[0].0.as_str(), "A");
assert!(matches!(
entries[0].1,
MaybeRef::NotRef(Object::Boolean(false))
));
assert_eq!(entries[1].0.as_str(), "C");
assert!(matches!(
entries[1].1,
MaybeRef::NotRef(Object::Boolean(true))
));
assert_eq!(
alloc::format!("{dict:?}"),
"Dict { \"A\": Boolean(false), \"C\": Boolean(true) }"
);
}
}
}