ion/format/
descriptor.rs

1/*
2 * This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
5 */
6
7use std::fmt;
8use std::fmt::{Display, Formatter, Write as _};
9
10use colored::Colorize as _;
11
12use crate::format::object::format_object;
13use crate::format::primitive::format_primitive;
14use crate::format::{Config, format_value};
15use crate::{Context, Function, Object, PropertyDescriptor};
16
17/// Formats a [descriptor](PropertyDescriptor) with the given [configuration](Config).
18pub fn format_descriptor<'cx>(
19	cx: &'cx Context, cfg: Config, desc: &'cx PropertyDescriptor<'cx>, object: Option<&'cx Object<'cx>>,
20) -> DescriptorDisplay<'cx> {
21	DescriptorDisplay { cx, cfg, desc, object }
22}
23
24#[must_use]
25pub struct DescriptorDisplay<'cx> {
26	cx: &'cx Context,
27	cfg: Config,
28	desc: &'cx PropertyDescriptor<'cx>,
29	object: Option<&'cx Object<'cx>>,
30}
31
32impl Display for DescriptorDisplay<'_> {
33	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
34		let color = self.cfg.colours.function;
35
36		if let Some(getter) = self.desc.getter(self.cx) {
37			"[Getter".color(color).fmt(f)?;
38			if self.desc.setter(self.cx).is_some() {
39				"/Setter".color(color).fmt(f)?;
40			}
41
42			if let Some(object) = self.object {
43				format_getter(f, self.cx, &getter, object, self.cfg)
44			} else {
45				"]".color(color).fmt(f)
46			}
47		} else if self.desc.setter(self.cx).is_some() {
48			"[Setter]".color(color).fmt(f)
49		} else {
50			match self.desc.value(self.cx) {
51				Some(value) => format_value(self.cx, self.cfg.depth(self.cfg.depth + 1).quoted(true), &value).fmt(f),
52				None => f.write_str("<empty descriptor>"),
53			}
54		}
55	}
56}
57
58fn format_getter(f: &mut Formatter<'_>, cx: &Context, getter: &Function, object: &Object, cfg: Config) -> fmt::Result {
59	let color = cfg.colours.function;
60
61	let value = match getter.call(cx, object, &[]) {
62		Ok(value) => value,
63		Err(report) => {
64			f.write_str(" <Inspection threw ")?;
65			match report {
66				Some(mut report) => {
67					report.stack = None;
68					f.write_char('(')?;
69					report.format(cx).fmt(f)?;
70					f.write_char(')')?;
71				}
72				None => f.write_str("unknown error")?,
73			}
74			f.write_char('>')?;
75			return "]".color(color).fmt(f);
76		}
77	};
78
79	if value.handle().is_object() {
80		"] ".color(color).fmt(f)?;
81		format_object(cx, cfg.depth(cfg.depth + 1).quoted(true), value.to_object(cx)).fmt(f)
82	} else {
83		": ".color(color).fmt(f)?;
84		format_primitive(cx, cfg.quoted(true), &value).fmt(f)?;
85		"]".color(color).fmt(f)
86	}
87}