summaryrefslogtreecommitdiffstats
path: root/gfx/wr/webrender/src/print_tree.rs
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/wr/webrender/src/print_tree.rs')
-rw-r--r--gfx/wr/webrender/src/print_tree.rs122
1 files changed, 122 insertions, 0 deletions
diff --git a/gfx/wr/webrender/src/print_tree.rs b/gfx/wr/webrender/src/print_tree.rs
new file mode 100644
index 0000000000..56d7852561
--- /dev/null
+++ b/gfx/wr/webrender/src/print_tree.rs
@@ -0,0 +1,122 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+use std::io::Write;
+use std::fmt::Write as FmtWrite;
+
+/// A struct that makes it easier to print out a pretty tree of data, which
+/// can be visually scanned more easily.
+pub struct PrintTree<W>
+where
+ W: Write
+{
+ /// The current level of recursion.
+ level: u32,
+
+ /// An item which is queued up, so that we can determine if we need
+ /// a mid-tree prefix or a branch ending prefix.
+ queued_item: Option<String>,
+
+ // We hold lines until they are done, and then output them all at
+ // once
+ line_buffer: String,
+
+ /// The sink to print to.
+ sink: W,
+}
+
+/// A trait that makes it easy to describe a pretty tree of data,
+/// regardless of the printing destination, to either print it
+/// directly to stdout, or serialize it as in the debugger
+pub trait PrintTreePrinter {
+ fn new_level(&mut self, title: String);
+ fn end_level(&mut self);
+ fn add_item(&mut self, text: String);
+}
+
+// The default does nothing but log
+impl PrintTree<std::io::Sink> {
+ pub fn new(title: &str) -> Self {
+ PrintTree::new_with_sink(title, std::io::sink())
+ }
+}
+
+impl<W> PrintTree<W>
+where
+ W: Write
+{
+ pub fn new_with_sink(title: &str, sink: W) -> Self {
+ let mut result = PrintTree {
+ level: 1,
+ queued_item: None,
+ line_buffer: String::new(),
+ sink,
+ };
+
+ writeln!(result.line_buffer, "\u{250c} {}", title).unwrap();
+ result.flush_line();
+ result
+ }
+
+ fn print_level_prefix(&mut self) {
+ for _ in 0 .. self.level {
+ write!(self.line_buffer, "\u{2502} ").unwrap();
+ }
+ }
+
+ fn flush_queued_item(&mut self, prefix: &str) {
+ if let Some(queued_item) = self.queued_item.take() {
+ self.print_level_prefix();
+ writeln!(self.line_buffer, "{} {}", prefix, queued_item).unwrap();
+ self.flush_line();
+ }
+ }
+
+ fn flush_line(&mut self) {
+ debug!("{}", self.line_buffer);
+ self.sink.write_all(self.line_buffer.as_bytes()).unwrap();
+ self.line_buffer.clear();
+ }
+}
+
+impl<W> PrintTreePrinter for PrintTree<W>
+where
+ W: Write
+{
+ /// Descend one level in the tree with the given title.
+ fn new_level(&mut self, title: String) {
+ self.flush_queued_item("\u{251C}\u{2500}");
+
+ self.print_level_prefix();
+ writeln!(self.line_buffer, "\u{251C}\u{2500} {}", title).unwrap();
+ self.flush_line();
+
+ self.level = self.level + 1;
+ }
+
+ /// Ascend one level in the tree.
+ fn end_level(&mut self) {
+ self.flush_queued_item("\u{2514}\u{2500}");
+ self.level = self.level - 1;
+ }
+
+ /// Add an item to the current level in the tree.
+ fn add_item(&mut self, text: String) {
+ self.flush_queued_item("\u{251C}\u{2500}");
+ self.queued_item = Some(text);
+ }
+}
+
+impl<W> Drop for PrintTree<W>
+where
+ W: Write
+{
+ fn drop(&mut self) {
+ self.flush_queued_item("\u{9492}\u{9472}");
+ }
+}
+
+pub trait PrintableTree {
+ fn print_with<T: PrintTreePrinter>(&self, pt: &mut T);
+}