ion/format/
string.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};
9
10use colored::Colorize as _;
11use encoding_rs::UTF_8;
12use mozjs::jsval::StringValue;
13
14use crate::format::Config;
15use crate::{Context, Local, Value};
16
17pub fn format_string<'cx>(cx: &'cx Context, cfg: Config, string: &'cx crate::String<'cx>) -> StringDisplay<'cx> {
18	StringDisplay { cx, string, cfg }
19}
20
21#[must_use]
22pub struct StringDisplay<'cx> {
23	cx: &'cx Context,
24	string: &'cx crate::String<'cx>,
25	cfg: Config,
26}
27
28impl Display for StringDisplay<'_> {
29	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
30		let colour = self.cfg.colours.string;
31		if self.cfg.quoted {
32			if let Ok(str) = self.string.to_owned(self.cx) {
33				write!(f, "{0}{1}{0}", r#"""#.color(colour), str.color(colour))
34			} else {
35				let value = StringValue(unsafe { &*self.string.get() });
36				let value = Value::from(unsafe { Local::from_marked(&raw const value) });
37				let str = value.to_source(self.cx).to_owned(self.cx).unwrap();
38				str.color(colour).fmt(f)
39			}
40		} else if let Ok(str) = self.string.to_owned(self.cx) {
41			str.fmt(f)
42		} else {
43			let input = self.string.as_wtf16(self.cx).unwrap();
44			let mut encoder = UTF_8.new_encoder();
45			let buf_len = encoder.max_buffer_length_from_utf16_if_no_unmappables(input.len()).unwrap();
46			let mut buf = Vec::with_capacity(buf_len);
47			let (_, _, _, _) = encoder.encode_from_utf16(input, &mut buf, true);
48			let str = unsafe { String::from_utf8_unchecked(buf) };
49			str.fmt(f)
50		}
51	}
52}