qframe/animation/
write.rs1use std::fmt::Write as _;
4
5use super::CellAnimation;
6use crate::icons::GlyphMode;
7
8impl CellAnimation {
9 #[must_use]
14 pub fn to_toml(&self, name: &str) -> String {
15 let mut out = format!("[animations.{name}]\n");
16 let _ = writeln!(out, "frame = {}", quoted(&self.frame_time.to_string()));
19 let _ = writeln!(out, "playback = {}", quoted(self.playback.name()));
20 let _ = writeln!(out, "colors = {}", quoted(self.colors.name()));
21 if let Some(rest) = self.rest {
22 let _ = writeln!(out, "rest = {}", rest + 1);
23 }
24 out.push_str("frames = [\n");
25 for frame in &self.frames {
26 let mut fields = Vec::new();
27 for (key, mode) in [("nerd", GlyphMode::Nerd), ("unicode", GlyphMode::Unicode), ("ascii", GlyphMode::Ascii)]
28 {
29 if let Some(glyph) = frame.own_glyph(mode) {
30 fields.push(format!("{key} = {}", quoted(glyph)));
31 }
32 }
33 if let Some(color) = &frame.color {
34 fields.push(format!("color = {}", quoted(color.as_str())));
35 }
36 if let Some(duration) = frame.duration {
37 fields.push(format!("duration = {}", quoted(&duration.to_string())));
38 }
39 let _ = writeln!(out, " {{ {} }},", fields.join(", "));
40 }
41 out.push_str("]\n");
42 out
43 }
44}
45
46fn quoted(text: &str) -> String {
48 let mut out = String::from("\"");
49 for c in text.chars() {
52 match c {
53 '"' => out.push_str("\\\""),
54 '\\' => out.push_str("\\\\"),
55 c if c.is_control() || is_private_use(c) => {
56 let code = u32::from(c);
57 if code > 0xFFFF {
58 let _ = write!(out, "\\U{code:08X}");
59 } else {
60 let _ = write!(out, "\\u{code:04X}");
61 }
62 }
63 c => out.push(c),
64 }
65 }
66 out.push('"');
67 out
68}
69
70fn is_private_use(c: char) -> bool {
72 matches!(u32::from(c), 0xE000..=0xF8FF | 0xF0000..=0xFFFFD | 0x10_0000..=0x10_FFFD)
73}