Skip to main content

latexml_core/
comment.rs

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    // Perl: Comment->getProperty('isEmpty') returns 1
33    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) {} // no-op
40  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  // sub getHeight      { return Dimension(0); }
59  // sub getTotalHeight { return Dimension(0); }
60  // sub getDepth       { return Dimension(0); }
61  // sub getSize { return (Dimension(0), Dimension(0), Dimension(0), Dimension(0), Dimension(0),
62  // Dimension(0)); }
63}
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    // Display of a Comment is always "" (comments produce no visible
84    // output).
85    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    // Perl: Comment->getProperty('isEmpty') returns 1.
101    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    // Other keys return None.
107    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    // Properties are always NO_PROPERTIES; nothing persists.
156    assert_eq!(c.get_properties().len(), 0);
157  }
158}