use super::*;
#[test]
fn test_sid_to_name_notdef() {
assert_eq!(sid_to_name(0), Some(".notdef"));
}
#[test]
fn test_sid_to_name_space() {
assert_eq!(sid_to_name(1), Some("space"));
}
#[test]
fn test_sid_to_name_letters() {
assert_eq!(sid_to_name(34), Some("A"));
assert_eq!(sid_to_name(59), Some("Z"));
assert_eq!(sid_to_name(66), Some("a"));
assert_eq!(sid_to_name(91), Some("z"));
}
#[test]
fn test_sid_to_name_digits() {
assert_eq!(sid_to_name(17), Some("zero"));
assert_eq!(sid_to_name(26), Some("nine"));
}
#[test]
fn test_sid_to_name_punctuation() {
assert_eq!(sid_to_name(2), Some("exclam"));
assert_eq!(sid_to_name(15), Some("period"));
assert_eq!(sid_to_name(13), Some("comma"));
}
#[test]
fn test_sid_to_name_ligatures() {
assert_eq!(sid_to_name(109), Some("fi"));
assert_eq!(sid_to_name(110), Some("fl"));
assert_eq!(sid_to_name(266), Some("ff"));
assert_eq!(sid_to_name(267), Some("ffi"));
assert_eq!(sid_to_name(268), Some("ffl"));
}
#[test]
fn test_sid_to_name_accented() {
assert_eq!(sid_to_name(171), Some("Aacute"));
assert_eq!(sid_to_name(200), Some("aacute"));
assert_eq!(sid_to_name(227), Some("ydieresis"));
}
#[test]
fn test_sid_to_name_last_entries() {
assert_eq!(sid_to_name(388), Some("Regular"));
assert_eq!(sid_to_name(389), Some("Roman"));
assert_eq!(sid_to_name(390), Some("Semibold"));
}
#[test]
fn test_sid_to_name_out_of_range() {
assert_eq!(sid_to_name(391), None);
assert_eq!(sid_to_name(500), None);
assert_eq!(sid_to_name(u16::MAX), None);
}
#[test]
fn test_parse_index_too_short() {
assert_eq!(parse_index(&[0x00], 0), None);
}
#[test]
fn test_parse_index_empty() {
let data = [0x00, 0x00];
let result = parse_index(&data, 0);
assert!(result.is_some());
let (entries, next) = result.unwrap();
assert!(entries.is_empty());
assert_eq!(next, 2);
}
#[test]
fn test_parse_index_single_entry() {
let data = vec![0x00, 0x01, 0x01, 0x01, 0x04, b'A', b'B', b'C'];
let result = parse_index(&data, 0);
assert!(result.is_some());
let (entries, _next) = result.unwrap();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0], b"ABC");
}
#[test]
fn test_parse_index_multiple_entries() {
let data = vec![0x00, 0x02, 0x01, 0x01, 0x03, 0x05, b'H', b'i', b'O', b'K'];
let result = parse_index(&data, 0);
assert!(result.is_some());
let (entries, _next) = result.unwrap();
assert_eq!(entries.len(), 2);
assert_eq!(entries[0], b"Hi");
assert_eq!(entries[1], b"OK");
}
#[test]
fn test_parse_index_invalid_off_size_zero() {
let data = vec![0x00, 0x01, 0x00];
assert_eq!(parse_index(&data, 0), None);
}
#[test]
fn test_parse_index_invalid_off_size_too_large() {
let data = vec![0x00, 0x01, 0x05];
assert_eq!(parse_index(&data, 0), None);
}
#[test]
fn test_parse_index_truncated_offset_array() {
let data = vec![0x00, 0x01, 0x01, 0x01];
assert_eq!(parse_index(&data, 0), None);
}
#[test]
fn test_parse_index_with_offset() {
let data = vec![0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x01, 0x01, 0x02, b'X'];
let result = parse_index(&data, 3);
assert!(result.is_some());
let (entries, _) = result.unwrap();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0], b"X");
}
#[test]
fn test_parse_index_off_size_2() {
let data = vec![0x00, 0x01, 0x02, 0x00, 0x01, 0x00, 0x03, b'A', b'B'];
let result = parse_index(&data, 0);
assert!(result.is_some());
let (entries, _) = result.unwrap();
assert_eq!(entries.len(), 1);
assert_eq!(entries[0], b"AB");
}
#[test]
fn test_parse_index_data_out_of_bounds() {
let data = vec![0x00, 0x01, 0x01, 0x01, 0xFF];
assert_eq!(parse_index(&data, 0), None);
}
#[test]
fn test_parse_dict_operand_empty() {
assert_eq!(parse_dict_operand(&[], 0), None);
}
#[test]
fn test_parse_dict_operand_single_byte_zero() {
assert_eq!(parse_dict_operand(&[139], 0), Some((0, 1)));
}
#[test]
fn test_parse_dict_operand_single_byte_positive() {
assert_eq!(parse_dict_operand(&[246], 0), Some((107, 1)));
}
#[test]
fn test_parse_dict_operand_single_byte_negative() {
assert_eq!(parse_dict_operand(&[32], 0), Some((-107, 1)));
}
#[test]
fn test_parse_dict_operand_two_byte_positive() {
assert_eq!(parse_dict_operand(&[247, 0], 0), Some((108, 2)));
assert_eq!(parse_dict_operand(&[250, 255], 0), Some((1131, 2)));
}
#[test]
fn test_parse_dict_operand_two_byte_negative() {
assert_eq!(parse_dict_operand(&[251, 0], 0), Some((-108, 2)));
assert_eq!(parse_dict_operand(&[254, 255], 0), Some((-1131, 2)));
}
#[test]
fn test_parse_dict_operand_two_byte_truncated() {
assert_eq!(parse_dict_operand(&[247], 0), None);
assert_eq!(parse_dict_operand(&[251], 0), None);
}
#[test]
fn test_parse_dict_operand_three_byte_int16() {
assert_eq!(parse_dict_operand(&[28, 0x00, 0x01], 0), Some((1, 3)));
assert_eq!(parse_dict_operand(&[28, 0xFF, 0xFF], 0), Some((-1, 3)));
assert_eq!(parse_dict_operand(&[28, 0x7F, 0xFF], 0), Some((32767, 3)));
}
#[test]
fn test_parse_dict_operand_three_byte_truncated() {
assert_eq!(parse_dict_operand(&[28, 0x00], 0), None);
}
#[test]
fn test_parse_dict_operand_five_byte_int32() {
assert_eq!(parse_dict_operand(&[29, 0x00, 0x00, 0x00, 0x01], 0), Some((1, 5)));
assert_eq!(parse_dict_operand(&[29, 0xFF, 0xFF, 0xFF, 0xFF], 0), Some((-1, 5)));
}
#[test]
fn test_parse_dict_operand_five_byte_truncated() {
assert_eq!(parse_dict_operand(&[29, 0x00, 0x00, 0x00], 0), None);
}
#[test]
fn test_parse_dict_operand_real_number() {
let data = [30, 0x1A, 0x5F];
let result = parse_dict_operand(&data, 0);
assert!(result.is_some());
let (val, consumed) = result.unwrap();
assert_eq!(val, 0);
assert_eq!(consumed, 3);
}
#[test]
fn test_parse_dict_operand_real_nibble1_end() {
let data = [30, 0xF0];
let result = parse_dict_operand(&data, 0);
assert!(result.is_some());
assert_eq!(result.unwrap(), (0, 2));
}
#[test]
fn test_parse_dict_operand_real_unterminated() {
let data = [30, 0x12, 0x34];
assert_eq!(parse_dict_operand(&data, 0), None);
}
#[test]
fn test_parse_dict_operand_unknown_byte() {
assert_eq!(parse_dict_operand(&[0], 0), None);
assert_eq!(parse_dict_operand(&[21], 0), None);
assert_eq!(parse_dict_operand(&[255], 0), None);
}
#[test]
fn test_parse_dict_operand_with_offset() {
let data = [0x00, 0x00, 139];
assert_eq!(parse_dict_operand(&data, 2), Some((0, 1)));
}
#[test]
fn test_parse_top_dict_empty() {
let (enc, charset) = parse_top_dict(&[]);
assert_eq!(enc, 0);
assert_eq!(charset, 0);
}
#[test]
fn test_parse_top_dict_encoding_offset() {
let data = [181, 16];
let (enc, charset) = parse_top_dict(&data);
assert_eq!(enc, 42);
assert_eq!(charset, 0);
}
#[test]
fn test_parse_top_dict_charset_offset() {
let data = [238, 15];
let (enc, charset) = parse_top_dict(&data);
assert_eq!(enc, 0);
assert_eq!(charset, 99);
}
#[test]
fn test_parse_top_dict_both_offsets() {
let data = [189, 16, 239, 15];
let (enc, charset) = parse_top_dict(&data);
assert_eq!(enc, 50);
assert_eq!(charset, 100);
}
#[test]
fn test_parse_top_dict_two_byte_operator() {
let data = [139, 12, 0];
let (enc, charset) = parse_top_dict(&data);
assert_eq!(enc, 0);
assert_eq!(charset, 0);
}
#[test]
fn test_parse_top_dict_unknown_operator() {
let data = [181, 17];
let (enc, charset) = parse_top_dict(&data);
assert_eq!(enc, 0);
assert_eq!(charset, 0);
}
#[test]
fn test_parse_top_dict_skip_unparseable() {
let data = [255, 181, 16];
let (enc, charset) = parse_top_dict(&data);
assert_eq!(enc, 42);
assert_eq!(charset, 0);
}
#[test]
fn test_parse_charset_out_of_bounds() {
assert_eq!(parse_charset(&[0x00], 5, 10), None);
}
#[test]
fn test_parse_charset_format0() {
let data = vec![0x00, 0x00, 0x01, 0x00, 0x22, 0x00, 0x42];
let result = parse_charset(&data, 0, 4);
assert!(result.is_some());
let sids = result.unwrap();
assert_eq!(sids.len(), 4);
assert_eq!(sids[0], 0);
assert_eq!(sids[1], 1);
assert_eq!(sids[2], 34);
assert_eq!(sids[3], 66);
}
#[test]
fn test_parse_charset_format1() {
let data = vec![0x01, 0x00, 0x22, 0x02];
let result = parse_charset(&data, 0, 4);
assert!(result.is_some());
let sids = result.unwrap();
assert_eq!(sids.len(), 4);
assert_eq!(sids[0], 0);
assert_eq!(sids[1], 34);
assert_eq!(sids[2], 35);
assert_eq!(sids[3], 36);
}
#[test]
fn test_parse_charset_format2() {
let data = vec![0x02, 0x00, 0x42, 0x00, 0x03];
let result = parse_charset(&data, 0, 5);
assert!(result.is_some());
let sids = result.unwrap();
assert_eq!(sids.len(), 5);
assert_eq!(sids[0], 0);
assert_eq!(sids[1], 66);
assert_eq!(sids[2], 67);
assert_eq!(sids[3], 68);
assert_eq!(sids[4], 69);
}
#[test]
fn test_parse_charset_unknown_format() {
let data = vec![0x03];
assert_eq!(parse_charset(&data, 0, 2), None);
}
#[test]
fn test_parse_charset_format0_truncated() {
let data = vec![0x00, 0x00];
let result = parse_charset(&data, 0, 3);
assert!(result.is_some());
let sids = result.unwrap();
assert_eq!(sids[0], 0);
}
#[test]
fn test_parse_charset_format1_limits_to_num_glyphs() {
let data = vec![0x01, 0x00, 0x01, 0xFF];
let result = parse_charset(&data, 0, 3);
assert!(result.is_some());
let sids = result.unwrap();
assert_eq!(sids.len(), 3);
}
#[test]
fn test_parse_encoding_table_out_of_bounds() {
assert_eq!(parse_encoding_table(&[0x00], 5), None);
}
#[test]
fn test_parse_encoding_table_format0() {
let data = vec![0x00, 0x03, 0x41, 0x42, 0x43];
let result = parse_encoding_table(&data, 0);
assert!(result.is_some());
let map = result.unwrap();
assert_eq!(map.get(&0x41), Some(&1));
assert_eq!(map.get(&0x42), Some(&2));
assert_eq!(map.get(&0x43), Some(&3));
}
#[test]
fn test_parse_encoding_table_format1() {
let data = vec![0x01, 0x01, 0x41, 0x02];
let result = parse_encoding_table(&data, 0);
assert!(result.is_some());
let map = result.unwrap();
assert_eq!(map.get(&0x41), Some(&1));
assert_eq!(map.get(&0x42), Some(&2));
assert_eq!(map.get(&0x43), Some(&3));
}
#[test]
fn test_parse_encoding_table_unknown_format() {
let data = vec![0x02];
assert_eq!(parse_encoding_table(&data, 0), None);
}
#[test]
fn test_parse_encoding_table_format0_truncated() {
let data = vec![0x00, 0x05, 0x41, 0x42];
let result = parse_encoding_table(&data, 0);
assert!(result.is_some());
let map = result.unwrap();
assert_eq!(map.len(), 2);
}
#[test]
fn test_parse_encoding_table_with_supplement() {
let data = vec![0x80, 0x01, 0x41, 0x01, 0x42, 0x00, 0x22];
let result = parse_encoding_table(&data, 0);
assert!(result.is_some());
let map = result.unwrap();
assert_eq!(map.get(&0x41), Some(&1));
assert_eq!(map.get(&0x42), Some(&34));
}
#[test]
fn test_parse_encoding_table_format1_truncated() {
let data = vec![0x01, 0x02, 0x41, 0x01];
let result = parse_encoding_table(&data, 0);
assert!(result.is_some());
let map = result.unwrap();
assert_eq!(map.len(), 2);
}
#[test]
fn test_parse_encoding_table_format0_empty_pos() {
let data = vec![0x00];
assert_eq!(parse_encoding_table(&data, 0), None);
}
#[test]
fn test_parse_encoding_table_format1_empty_pos() {
let data = vec![0x01];
assert_eq!(parse_encoding_table(&data, 0), None);
}
#[test]
fn test_resolve_glyph_name_predefined() {
let string_index: Vec<&[u8]> = vec![];
assert_eq!(resolve_glyph_name(0, &string_index), Some(".notdef".to_string()));
assert_eq!(resolve_glyph_name(1, &string_index), Some("space".to_string()));
assert_eq!(resolve_glyph_name(34, &string_index), Some("A".to_string()));
assert_eq!(resolve_glyph_name(390, &string_index), Some("Semibold".to_string()));
}
#[test]
fn test_resolve_glyph_name_custom_string() {
let custom: Vec<&[u8]> = vec![b"MyGlyph", b"AnotherGlyph"];
assert_eq!(resolve_glyph_name(391, &custom), Some("MyGlyph".to_string()));
assert_eq!(resolve_glyph_name(392, &custom), Some("AnotherGlyph".to_string()));
}
#[test]
fn test_resolve_glyph_name_custom_out_of_range() {
let custom: Vec<&[u8]> = vec![b"OnlyOne"];
assert_eq!(resolve_glyph_name(393, &custom), None);
}
#[test]
fn test_resolve_glyph_name_custom_invalid_utf8() {
let invalid_utf8: Vec<&[u8]> = vec![&[0xFF, 0xFE]];
assert_eq!(resolve_glyph_name(391, &invalid_utf8), None);
}
#[test]
fn test_extract_cff_from_opentype_too_short() {
assert_eq!(extract_cff_from_opentype(&[0; 8]), None);
}
#[test]
fn test_extract_cff_from_opentype_not_opentype() {
let data = vec![0x00; 16];
assert_eq!(extract_cff_from_opentype(&data), None);
}
#[test]
fn test_extract_cff_from_opentype_otto_no_cff_table() {
let data = vec![0x4F, 0x54, 0x54, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
assert_eq!(extract_cff_from_opentype(&data), None);
}
#[test]
fn test_extract_cff_from_opentype_with_cff_table() {
let cff_data = b"\x01\x00\x04\x01";
let cff_offset: u32 = 28;
let cff_length: u32 = cff_data.len() as u32;
let mut data = vec![0x4F, 0x54, 0x54, 0x4F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00];
data.extend_from_slice(b"CFF ");
data.extend_from_slice(&[0, 0, 0, 0]);
data.extend_from_slice(&cff_offset.to_be_bytes());
data.extend_from_slice(&cff_length.to_be_bytes());
data.extend_from_slice(cff_data);
let result = extract_cff_from_opentype(&data);
assert!(result.is_some());
assert_eq!(result.unwrap(), cff_data);
}
#[test]
fn test_extract_cff_from_opentype_truncated_table_dir() {
let data = vec![
0x4F, 0x54, 0x54, 0x4F, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, b'C', b'F',
];
assert_eq!(extract_cff_from_opentype(&data), None);
}
#[test]
fn test_parse_cff_encoding_too_short() {
assert_eq!(parse_cff_encoding(&[0, 1, 2]), None);
}
#[test]
fn test_parse_cff_encoding_wrong_version() {
let data = vec![0x02, 0x00, 0x04, 0x01, 0x00];
assert_eq!(parse_cff_encoding(&data), None);
}
#[test]
fn test_parse_cff_encoding_version1_too_short_after_check() {
let data = vec![0x01, 0x00, 0x04];
assert_eq!(parse_cff_encoding(&data), None);
}
#[test]
fn test_parse_cff_encoding_expert_encoding() {
let data = build_minimal_cff(1, 0);
let result = parse_cff_encoding(&data);
assert_eq!(result, None);
}
#[test]
fn test_parse_cff_encoding_standard_encoding_default_charset() {
let data = build_minimal_cff(0, 0);
let result = parse_cff_encoding(&data);
assert_eq!(result, None);
}
fn build_minimal_cff(encoding_offset: i32, charset_offset: i32) -> Vec<u8> {
let mut data = vec![1, 0, 4, 1];
append_index(&mut data, &[b"Test"]);
let top_dict = build_top_dict(encoding_offset, charset_offset);
append_index(&mut data, &[&top_dict]);
append_index(&mut data, &[]);
append_index(&mut data, &[]);
data
}
fn build_top_dict(encoding_offset: i32, charset_offset: i32) -> Vec<u8> {
let mut dict = Vec::new();
encode_dict_int(&mut dict, encoding_offset);
dict.push(16);
encode_dict_int(&mut dict, charset_offset);
dict.push(15);
dict
}
fn encode_dict_int(out: &mut Vec<u8>, val: i32) {
if (-107..=107).contains(&val) {
out.push((val + 139) as u8);
} else if (108..=1131).contains(&val) {
let v = val - 108;
out.push((v / 256 + 247) as u8);
out.push((v % 256) as u8);
} else if (-1131..=-108).contains(&val) {
let v = -val - 108;
out.push((v / 256 + 251) as u8);
out.push((v % 256) as u8);
} else if (-32768..=32767).contains(&val) {
out.push(28);
let bytes = (val as i16).to_be_bytes();
out.push(bytes[0]);
out.push(bytes[1]);
} else {
out.push(29);
let bytes = val.to_be_bytes();
out.extend_from_slice(&bytes);
}
}
fn append_index(data: &mut Vec<u8>, entries: &[&[u8]]) {
let count = entries.len() as u16;
data.extend_from_slice(&count.to_be_bytes());
if count == 0 {
return;
}
data.push(1);
let mut offset: u8 = 1;
data.push(offset);
for entry in entries {
offset += entry.len() as u8;
data.push(offset);
}
for entry in entries {
data.extend_from_slice(entry);
}
}
#[test]
fn test_glyph_name_to_sid_known_names() {
assert_eq!(glyph_name_to_sid(".notdef"), Some(0));
assert_eq!(glyph_name_to_sid("space"), Some(1));
assert_eq!(glyph_name_to_sid("A"), Some(34));
assert_eq!(glyph_name_to_sid("B"), Some(35));
assert_eq!(glyph_name_to_sid("Z"), Some(59));
assert_eq!(glyph_name_to_sid("a"), Some(66));
assert_eq!(glyph_name_to_sid("z"), Some(91));
assert_eq!(glyph_name_to_sid("zero"), Some(17));
assert_eq!(glyph_name_to_sid("nine"), Some(26));
}
#[test]
fn test_glyph_name_to_sid_unknown() {
assert_eq!(glyph_name_to_sid("nonexistent_glyph_xyz"), None);
assert_eq!(glyph_name_to_sid(""), None);
}
#[test]
fn test_glyph_name_to_sid_roundtrip() {
for sid in 0u16..391 {
if let Some(name) = sid_to_name(sid) {
assert_eq!(
glyph_name_to_sid(name),
Some(sid),
"Roundtrip failed for SID {} (name '{}')",
sid,
name
);
}
}
}
#[test]
fn test_parse_cff_gid_mapping_invalid_data() {
assert!(parse_cff_gid_mapping(&[]).is_none());
assert!(parse_cff_gid_mapping(&[0, 1, 2]).is_none());
assert!(parse_cff_gid_mapping(&[2, 0, 4, 2]).is_none());
}
use crate::fonts::font_dict::Encoding;
#[test]
fn resolve_via_pdf_encoding_recovers_all_charset_glyphs() {
let charset = [0u16, 1, 34, 35, 36, 48, 55, 47];
let string_index: Vec<&[u8]> = Vec::new();
let pdf_enc = Encoding::Standard("WinAnsiEncoding".to_string());
let differences: HashMap<u8, String> = HashMap::new();
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert_eq!(map.get(&0x20), Some(&1), "0x20 (space) → GID 1");
assert_eq!(map.get(&0x41), Some(&2), "0x41 (A) → GID 2");
assert_eq!(map.get(&0x42), Some(&3), "0x42 (B) → GID 3");
assert_eq!(map.get(&0x43), Some(&4), "0x43 (C) → GID 4");
assert_eq!(map.get(&0x4f), Some(&5), "0x4f (O) → GID 5");
assert_eq!(map.get(&0x56), Some(&6), "0x56 (V) → GID 6");
assert_eq!(map.get(&0x4e), Some(&7), "0x4e (N) → GID 7");
assert!(!map.contains_key(&0x7e), "0x7e (asciitilde) not in charset");
}
#[test]
fn resolve_via_pdf_encoding_honors_differences_array() {
let charset = [0u16, 116];
let string_index: Vec<&[u8]> = Vec::new();
let pdf_enc = Encoding::Standard("WinAnsiEncoding".to_string());
let mut differences = HashMap::new();
differences.insert(0x95u8, "bullet".to_string());
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert_eq!(map.get(&0x95), Some(&1));
}
#[test]
fn resolve_via_pdf_encoding_skips_identity() {
let charset = [0u16, 34];
let string_index: Vec<&[u8]> = Vec::new();
let pdf_enc = Encoding::Identity;
let differences: HashMap<u8, String> = HashMap::new();
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert!(map.is_empty(), "Identity → no base byte→name resolution");
}
#[test]
fn resolve_via_pdf_encoding_resolves_custom_string_sids() {
let charset = [0u16, 391];
let custom: &[u8] = b"customGlyph";
let string_index: Vec<&[u8]> = vec![custom];
let pdf_enc = Encoding::Standard("WinAnsiEncoding".to_string());
let mut differences = HashMap::new();
differences.insert(0x21u8, "customGlyph".to_string());
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert_eq!(map.get(&0x21), Some(&1));
}
#[test]
fn resolve_via_pdf_encoding_uses_mac_roman_table_for_mac_base() {
let charset: Vec<u16> = vec![0, 173, 391];
let string_index: Vec<&[u8]> = vec![b"euro"];
let differences: HashMap<u8, String> = HashMap::new();
let pdf_enc = Encoding::Standard("MacRomanEncoding".to_string());
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert_eq!(map.get(&0x80), Some(&1), "MacRoman 0x80 → Adieresis (GID 1)");
}
#[test]
fn resolve_via_pdf_encoding_uses_standard_encoding_table_for_standard_base() {
let charset: Vec<u16> = vec![0, 99, 103];
let string_index: Vec<&[u8]> = vec![];
let differences: HashMap<u8, String> = HashMap::new();
let pdf_enc = Encoding::Standard("StandardEncoding".to_string());
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert_eq!(map.get(&0xA4), Some(&1), "StandardEncoding 0xA4 → fraction (GID 1)");
}
#[test]
fn resolve_via_pdf_encoding_uses_winansi_table_for_winansi_base() {
let charset: Vec<u16> = vec![0, 173, 391];
let string_index: Vec<&[u8]> = vec![b"euro"];
let differences: HashMap<u8, String> = HashMap::new();
let pdf_enc = Encoding::Standard("WinAnsiEncoding".to_string());
let map = resolve_bytes_via_pdf_encoding(&charset, &string_index, &pdf_enc, &differences);
assert_eq!(map.get(&0x80), Some(&2), "WinAnsi 0x80 → euro (GID 2)");
}
#[test]
fn parse_charset_format0_handles_more_than_256_entries() {
let mut data = vec![0x00u8];
for gid in 1u16..=299u16 {
data.extend_from_slice(&gid.to_be_bytes());
}
let sids = parse_charset(&data, 0, 300).expect("parse_charset returned None");
assert_eq!(sids.len(), 300, "300 entries (GID 0 + 299 enumerated)");
assert_eq!(sids[0], 0, "GID 0 is .notdef (SID 0)");
assert_eq!(sids[1], 1, "GID 1 → SID 1");
assert_eq!(sids[256], 256, "GID 256 → SID 256 (past the old 256 cap)");
assert_eq!(sids[299], 299, "GID 299 → SID 299 (last entry)");
}
#[test]
fn parse_top_dict_surfaces_charstrings_offset() {
let mut dict = vec![28u8];
dict.extend_from_slice(&1234i16.to_be_bytes());
dict.push(17u8);
let (charstrings_offset, _enc, _charset) = parse_top_dict_with_charstrings(&dict);
assert_eq!(charstrings_offset, 1234, "Top DICT op 17 → CharStrings offset");
}
#[test]
fn read_index_count_returns_header_count() {
let data = [0x01u8, 0x2C];
assert_eq!(read_index_count(&data, 0), Some(300));
}