use oxidize_pdf::parser::objects::{
PdfArray, PdfDictionary, PdfName, PdfObject, PdfStream, PdfString,
};
#[test]
fn test_object_creation_and_conversion() {
let null = PdfObject::Null;
let boolean = PdfObject::Boolean(true);
let integer = PdfObject::Integer(42);
let real = PdfObject::Real(3.14159);
let string = PdfObject::String(PdfString::new(b"Hello PDF".to_vec()));
let name = PdfObject::Name(PdfName::new("Type".to_string()));
assert!(null.is_null());
assert!(boolean.as_bool().is_some());
assert_eq!(integer.as_integer(), Some(42));
assert!(real.as_real().is_some());
assert!(string.as_string().is_some());
assert!(name.as_name().is_some());
}
#[test]
fn test_array_operations() {
let mut array = PdfArray(Vec::new());
array.0.push(PdfObject::Integer(1));
array.0.push(PdfObject::Real(2.5));
array
.0
.push(PdfObject::String(PdfString::new(b"text".to_vec())));
array.0.push(PdfObject::Boolean(true));
array.0.push(PdfObject::Null);
assert_eq!(array.0.len(), 5);
assert_eq!(array.0[0].as_integer(), Some(1));
assert!(array.0[4].is_null());
let mut nested = PdfArray(Vec::new());
nested.0.push(PdfObject::Integer(10));
nested.0.push(PdfObject::Integer(20));
array.0.push(PdfObject::Array(nested));
assert_eq!(array.0.len(), 6);
}
#[test]
fn test_dictionary_operations() {
let mut dict = PdfDictionary::new();
dict.insert(
"Type".to_string(),
PdfObject::Name(PdfName::new("Page".to_string())),
);
dict.insert("Count".to_string(), PdfObject::Integer(10));
dict.insert(
"Title".to_string(),
PdfObject::String(PdfString::new(b"Test".to_vec())),
);
assert_eq!(dict.0.len(), 3);
assert!(dict.0.contains_key(&PdfName::new("Type".to_string())));
let mut nested = PdfDictionary::new();
nested.insert("Nested".to_string(), PdfObject::Boolean(true));
dict.insert("SubDict".to_string(), PdfObject::Dictionary(nested));
assert_eq!(dict.0.len(), 4);
}
#[test]
fn test_stream_object() {
let mut dict = PdfDictionary::new();
dict.insert("Length".to_string(), PdfObject::Integer(100));
dict.insert(
"Filter".to_string(),
PdfObject::Name(PdfName::new("FlateDecode".to_string())),
);
let data = b"This is stream data that would normally be compressed".to_vec();
let stream = PdfStream {
dict: dict.clone(),
data: data.clone(),
};
assert_eq!(stream.data, data);
assert!(stream
.dict
.0
.contains_key(&PdfName::new("Length".to_string())));
}
#[test]
fn test_object_references() {
let ref1 = PdfObject::Reference(10, 0);
let ref2 = PdfObject::Reference(20, 1);
assert!(ref1.as_reference().is_some());
assert_eq!(ref1.as_reference(), Some((10, 0)));
assert_eq!(ref2.as_reference(), Some((20, 1)));
let mut array = PdfArray(Vec::new());
array.0.push(ref1);
array.0.push(ref2);
array.0.push(PdfObject::Integer(5));
assert_eq!(array.0.len(), 3);
}
#[test]
fn test_complex_nested_structures() {
let mut page = PdfDictionary::new();
page.insert(
"Type".to_string(),
PdfObject::Name(PdfName::new("Page".to_string())),
);
page.insert("Parent".to_string(), PdfObject::Reference(1, 0));
let mut media_box = PdfArray(Vec::new());
media_box.0.push(PdfObject::Integer(0));
media_box.0.push(PdfObject::Integer(0));
media_box.0.push(PdfObject::Real(612.0));
media_box.0.push(PdfObject::Real(792.0));
page.insert("MediaBox".to_string(), PdfObject::Array(media_box));
let mut resources = PdfDictionary::new();
let mut fonts = PdfDictionary::new();
let mut f1 = PdfDictionary::new();
f1.insert(
"Type".to_string(),
PdfObject::Name(PdfName::new("Font".to_string())),
);
f1.insert(
"Subtype".to_string(),
PdfObject::Name(PdfName::new("Type1".to_string())),
);
f1.insert(
"BaseFont".to_string(),
PdfObject::Name(PdfName::new("Helvetica".to_string())),
);
fonts.insert("F1".to_string(), PdfObject::Dictionary(f1));
resources.insert("Font".to_string(), PdfObject::Dictionary(fonts));
page.insert("Resources".to_string(), PdfObject::Dictionary(resources));
page.insert("Contents".to_string(), PdfObject::Reference(4, 0));
let page_map = page.0;
assert!(page_map.contains_key(&PdfName::new("Type".to_string())));
assert!(page_map.contains_key(&PdfName::new("MediaBox".to_string())));
assert!(page_map.contains_key(&PdfName::new("Resources".to_string())));
}
#[test]
fn test_string_types() {
let literal = PdfString::new(b"Hello (World)".to_vec());
assert_eq!(literal.as_bytes(), b"Hello (World)");
let escaped = PdfString::new(b"Line 1\\nLine 2\\t\\(escaped\\)".to_vec());
assert!(!escaped.as_bytes().is_empty());
let binary = PdfString::new(vec![0xFF, 0x00, 0xAB, 0xCD]);
assert_eq!(binary.as_bytes().len(), 4);
let unicode_marker = vec![0xFE, 0xFF]; let mut unicode = unicode_marker;
unicode.extend_from_slice(&[0x00, 0x48, 0x00, 0x69]); let unicode_str = PdfString::new(unicode);
assert!(unicode_str.as_bytes().starts_with(&[0xFE, 0xFF]));
}
#[test]
fn test_name_objects() {
let name1 = PdfName::new("Type".to_string());
let name2 = PdfName::new("Page".to_string());
assert_eq!(name1.as_str(), "Type");
assert_eq!(name2.as_str(), "Page");
let special = PdfName::new("Name#20with#20spaces".to_string());
assert!(special.as_str().contains("#20"));
let mut dict = PdfDictionary::new();
dict.insert(name1.as_str().to_string(), PdfObject::Name(name2));
assert_eq!(dict.0.len(), 1);
}
#[test]
fn test_object_equality() {
let int1 = PdfObject::Integer(42);
let int2 = PdfObject::Integer(42);
let int3 = PdfObject::Integer(43);
assert_eq!(int1, int2);
assert_ne!(int1, int3);
let mut arr1 = PdfArray(Vec::new());
arr1.0.push(PdfObject::Integer(1));
arr1.0.push(PdfObject::Integer(2));
let mut arr2 = PdfArray(Vec::new());
arr2.0.push(PdfObject::Integer(1));
arr2.0.push(PdfObject::Integer(2));
assert_eq!(PdfObject::Array(arr1), PdfObject::Array(arr2));
let mut dict1 = PdfDictionary::new();
dict1.insert("Key".to_string(), PdfObject::Integer(10));
let mut dict2 = PdfDictionary::new();
dict2.insert("Key".to_string(), PdfObject::Integer(10));
assert_eq!(PdfObject::Dictionary(dict1), PdfObject::Dictionary(dict2));
}
#[test]
fn test_object_type_conversions() {
let boolean = PdfObject::Boolean(true);
let integer = PdfObject::Integer(42);
let real = PdfObject::Real(3.14);
let string = PdfObject::String(PdfString::new(b"text".to_vec()));
assert_eq!(boolean.as_bool(), Some(true));
assert_eq!(boolean.as_integer(), None);
assert_eq!(integer.as_integer(), Some(42));
assert_eq!(integer.as_bool(), None);
assert!(real.as_real().is_some());
assert_eq!(real.as_string(), None);
assert!(string.as_string().is_some());
assert_eq!(string.as_real(), None);
assert!(boolean.as_bool().is_some());
assert!(boolean.as_integer().is_none());
assert!(integer.as_integer().is_some());
assert_eq!(integer.as_real(), Some(42.0));
assert!(real.as_real().is_some());
assert!(real.as_string().is_none());
}
#[test]
fn test_large_dictionary() {
let mut dict = PdfDictionary::new();
for i in 0..100 {
let key = format!("Key{}", i);
let value = if i % 2 == 0 {
PdfObject::Integer(i as i64)
} else {
PdfObject::String(PdfString::new(format!("Value{}", i).into_bytes()))
};
dict.insert(key, value);
}
assert_eq!(dict.0.len(), 100);
assert!(dict.0.contains_key(&PdfName::new("Key0".to_string())));
assert!(dict.0.contains_key(&PdfName::new("Key99".to_string())));
}
#[test]
fn test_deeply_nested_structures() {
let mut root = PdfDictionary::new();
for level in 0..5 {
let mut dict = PdfDictionary::new();
dict.insert("Level".to_string(), PdfObject::Integer(level));
let mut array = PdfArray(Vec::new());
for i in 0..3 {
array.0.push(PdfObject::Integer(i));
}
dict.insert("Data".to_string(), PdfObject::Array(array));
if level > 0 {
dict.insert(
"Parent".to_string(),
PdfObject::Reference(level as u32 - 1, 0),
);
}
root.insert(format!("Level{}", level), PdfObject::Dictionary(dict));
}
assert_eq!(root.0.len(), 5);
}