weakauras_codec_ace_serialize/serialization/
mod.rs1use crate::{error::SerializationError, macros::check_recursion};
5use weakauras_codec_lua_value::LuaValue;
6
7fn f64_to_parts(v: f64) -> (u64, i16, i8) {
8 let bits = v.to_bits();
9 let sign: i8 = if bits >> 63 == 0 { 1 } else { -1 };
10 let mut exponent: i16 = ((bits >> 52) & 0x7ff) as i16;
11 let mantissa = if exponent == 0 {
12 (bits & 0xfffffffffffff) << 1
13 } else {
14 (bits & 0xfffffffffffff) | 0x10000000000000
15 };
16 exponent -= 1023 + 52;
17 (mantissa, exponent, sign)
18}
19
20fn write_integer_to_a_string<I>(string: &mut String, value: I)
21where
22 I: itoa::Integer,
23{
24 let mut buffer = itoa::Buffer::new();
25 let serialized = buffer.format(value);
26 string.push_str(serialized)
27}
28
29pub struct Serializer {
45 remaining_depth: usize,
46 result: String,
47}
48
49impl Serializer {
50 pub fn serialize_one(
52 value: &LuaValue,
53 approximate_len: Option<usize>,
54 ) -> Result<String, SerializationError> {
55 let mut serializer = Self {
56 remaining_depth: 128,
57 result: String::with_capacity(approximate_len.unwrap_or(1024)),
58 };
59
60 serializer.result.push_str("^1");
61 serializer.serialize_helper(value)?;
62 serializer.result.push_str("^^");
63
64 Ok(serializer.result)
65 }
66
67 fn serialize_helper(&mut self, value: &LuaValue) -> Result<(), SerializationError> {
68 match *value {
69 LuaValue::Null => self.result.push_str("^Z"),
70 LuaValue::Boolean(b) => self.result.push_str(if b { "^B" } else { "^b" }),
71 LuaValue::String(ref s) => {
72 self.result.push_str("^S");
73 self.serialize_string(s)
74 }
75 LuaValue::Number(n) => self.serialize_number(n)?,
76 LuaValue::Array(ref v) => {
77 self.result.reserve(v.len() * 6 + 4);
78
79 self.result.push_str("^T");
80 for (value, index) in v.iter().zip(1..) {
81 self.serialize_number(index as f64)?;
82 self.serialize_helper(value)?;
83 }
84 self.result.push_str("^t");
85 }
86 LuaValue::Map(ref m) => {
87 self.result.reserve(m.len() * 6 + 4);
88
89 self.result.push_str("^T");
90 for (key, value) in m.iter() {
91 check_recursion!(self, SerializationError, {
92 self.serialize_helper(key.as_value())?;
93 self.serialize_helper(value)?;
94 });
95 }
96 self.result.push_str("^t");
97 }
98 }
99
100 Ok(())
101 }
102
103 fn serialize_number(&mut self, value: f64) -> Result<(), SerializationError> {
104 if value.is_nan() {
105 return Err(SerializationError::NanEncountered);
106 } else if !value.is_finite() {
107 self.result.push_str("^N");
108 self.result
109 .push_str(if value > 0.0 { "1.#INF" } else { "-1.#INF" })
110 } else {
111 let mut buffer = zmij::Buffer::new();
112 let str_value = buffer.format_finite(value);
113
114 if str_value.parse::<f64>().unwrap() == value {
115 self.result.reserve(str_value.len() + 2);
116 self.result.push_str("^N");
117 self.result.push_str(str_value);
118 } else {
119 let (mantissa, exponent, sign) = f64_to_parts(value);
120 self.result.push_str("^F");
121 if sign < 0 {
122 self.result.push('-');
123 }
124 write_integer_to_a_string(&mut self.result, mantissa);
125 self.result.push_str("^f");
126 write_integer_to_a_string(&mut self.result, exponent);
127 }
128 }
129
130 Ok(())
131 }
132
133 fn serialize_string(&mut self, value: &str) {
134 self.result.reserve(value.len());
135
136 let mut copy_from = 0;
137 for (i, byte) in value.bytes().enumerate() {
138 let replacement = match byte {
139 v @ 0x00..=0x1D | v @ 0x1F..=0x20 => v + 64,
140 0x1E => 0x7A,
141 0x5E => 0x7D,
142 0x7E => 0x7C,
143 0x7F => 0x7B,
144 _ => continue,
145 };
146
147 self.result.push_str(&value[copy_from..i]);
148 self.result.push('~');
149 self.result.push(replacement as char);
150 copy_from = i + 1;
151 }
152
153 self.result.push_str(&value[copy_from..]);
154 }
155}