1use std::{borrow::Cow, fmt, rc::Rc};
2
3use libxml::tree::Node;
4
5use crate::{
6 BoxOps, NO_PROPERTIES,
7 common::{
8 arena::SymHashMap as HashMap, dimension::Dimension, error::*, font::Font,
9 numeric_ops::NumericOps, object::Object, store::Stored,
10 },
11 definition::register::RegisterValue,
12 document::Document,
13 tokens::{NO_TOKENS, Tokens},
14};
15
16#[derive(Debug, Clone, Default, PartialEq, Eq)]
17pub struct Comment(pub String);
18
19impl fmt::Display for Comment {
20 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "") }
21}
22impl Object for Comment {
23 fn revert(&self) -> Result<Tokens> { Ok(NO_TOKENS) }
24}
25impl BoxOps for Comment {
26 fn get_properties(&self) -> &HashMap<Stored> { &NO_PROPERTIES }
27 fn with_properties<R, FnR>(&self, caller: FnR) -> R
28 where FnR: FnOnce(&HashMap<Stored>) -> R {
29 caller(&NO_PROPERTIES)
30 }
31 fn get_property(&self, key: &str) -> Option<Cow<'_, Stored>> {
32 if key == "isEmpty" {
34 Some(Cow::Owned(Stored::Bool(true)))
35 } else {
36 None
37 }
38 }
39 fn set_property<T: Into<Stored>>(&mut self, _key: &str, _value: T) {} fn get_string(&self) -> Result<Cow<'_, str>> { Ok(Cow::Borrowed(&self.0)) }
41 fn be_absorbed(&self, document: &mut Document) -> Result<Vec<Node>> {
42 document.insert_comment(&self.0)?;
43 Ok(Vec::new())
44 }
45 fn get_font(&self) -> Result<Option<Rc<Font>>> { Ok(None) }
46 fn get_width(&self, _options: Option<HashMap<Stored>>) -> Result<Option<RegisterValue>> {
47 Ok(Some(RegisterValue::Dimension(Dimension::new(0))))
48 }
49
50 fn compute_size(&self, _options: HashMap<Stored>) -> Result<(Dimension, Dimension, Dimension)> {
51 Ok((
52 Dimension::default(),
53 Dimension::default(),
54 Dimension::default(),
55 ))
56 }
57
58 }
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn comment_default_is_empty_string() {
71 let c = Comment::default();
72 assert_eq!(c.0, "");
73 }
74
75 #[test]
76 fn comment_new_holds_content() {
77 let c = Comment("% this is a comment".to_string());
78 assert_eq!(c.0, "% this is a comment");
79 }
80
81 #[test]
82 fn comment_display_is_always_empty_string() {
83 let c = Comment("visible".to_string());
86 assert_eq!(format!("{c}"), "");
87 let c2 = Comment::default();
88 assert_eq!(format!("{c2}"), "");
89 }
90
91 #[test]
92 fn comment_revert_yields_empty_tokens() {
93 let c = Comment("any".to_string());
94 let t = c.revert().unwrap();
95 assert_eq!(t.len(), 0);
96 }
97
98 #[test]
99 fn comment_is_empty_property() {
100 let c = Comment("anything".to_string());
102 match c.get_property("isEmpty") {
103 Some(Cow::Owned(Stored::Bool(true))) => {},
104 other => panic!("expected Some(Bool(true)), got {other:?}"),
105 }
106 assert!(c.get_property("random_key").is_none());
108 }
109
110 #[test]
111 fn comment_get_string_returns_content() {
112 let c = Comment("hello".to_string());
113 let s = c.get_string().unwrap();
114 assert_eq!(s.as_ref(), "hello");
115 }
116
117 #[test]
118 fn comment_equality() {
119 let a = Comment("x".to_string());
120 let b = Comment("x".to_string());
121 let c = Comment("y".to_string());
122 assert_eq!(a, b);
123 assert_ne!(a, c);
124 }
125
126 #[test]
127 fn comment_get_font_is_none() {
128 let c = Comment::default();
129 assert!(c.get_font().unwrap().is_none());
130 }
131
132 #[test]
133 fn comment_get_width_is_zero() {
134 let c = Comment::default();
135 let w = c.get_width(None).unwrap();
136 match w {
137 Some(RegisterValue::Dimension(d)) => assert_eq!(d.value_of(), 0),
138 other => panic!("expected Dimension(0), got {other:?}"),
139 }
140 }
141
142 #[test]
143 fn comment_compute_size_all_zero() {
144 let c = Comment::default();
145 let (w, h, d) = c.compute_size(HashMap::default()).unwrap();
146 assert_eq!(w.value_of(), 0);
147 assert_eq!(h.value_of(), 0);
148 assert_eq!(d.value_of(), 0);
149 }
150
151 #[test]
152 fn comment_set_property_noop() {
153 let mut c = Comment("x".to_string());
154 c.set_property("any", Stored::Bool(true));
155 assert_eq!(c.get_properties().len(), 0);
157 }
158}