1use std::{fs::File, path::Path};
2
3use serde::ser::Serialize as _;
4
5use super::error::{Error, Result};
6
7cfg_if::cfg_if! {
8 if #[cfg(feature = "debug")] {
9 use log::debug;
10 } else {
11 #[allow(unused_macros)]
12 macro_rules! debug {
13 ($fmt:expr $(, $arg:expr)*) => {};
14 }
15 }
16}
17
18pub struct Serializer {
20 output: String,
21 base_prefix: String,
22 prefix: String,
23 key: bool,
24 sequence: bool,
25 prefix_before: String,
26}
27
28impl Serializer {
29 fn new(prefix: Option<&str>) -> Self {
30 Self {
31 output: String::new(),
32 base_prefix: prefix.unwrap_or("").to_uppercase(),
33 prefix: "".into(),
34 key: false,
35 sequence: false,
36 prefix_before: "".into(),
37 }
38 }
39
40 pub(crate) fn strip_line_breaks(&mut self) {
41 while self.output.ends_with('\n') {
42 self.output = self.output[..self.output.len() - 1].into();
43 }
44 }
45}
46
47pub fn to_string<T>(v: &T) -> Result<String>
60where
61 T: serde::ser::Serialize,
62{
63 to_string_inner(None, v)
64}
65
66pub fn to_string_inner<T>(prefix: Option<&str>, v: &T) -> Result<String>
67where
68 T: serde::ser::Serialize,
69{
70 let mut serializer = Serializer::new(prefix);
71 v.serialize(&mut serializer)?;
72
73 Ok(serializer.output)
74}
75
76pub fn to_writer<W, T>(writer: W, v: &T) -> Result<()>
93where
94 W: std::io::Write,
95 T: serde::ser::Serialize,
96{
97 to_writer_inner(None, writer, v)
98}
99
100pub(crate) fn to_writer_inner<W, T>(prefix: Option<&str>, mut writer: W, v: &T) -> Result<()>
101where
102 W: std::io::Write,
103 T: serde::ser::Serialize,
104{
105 writer
106 .write_all(to_string_inner(prefix, v)?.as_bytes())
107 .map_err(Error::new)
108}
109
110pub fn to_file<P, T>(path: P, v: &T) -> Result<()>
124where
125 P: AsRef<Path>,
126 T: serde::ser::Serialize,
127{
128 to_file_inner(None, path, v)
129}
130
131pub fn to_file_inner<P, T>(prefix: Option<&str>, path: P, v: &T) -> Result<()>
132where
133 P: AsRef<Path>,
134 T: serde::ser::Serialize,
135{
136 let file = File::create(path).map_err(Error::new)?;
137 to_writer_inner(prefix, file, v)
138}
139
140impl serde::ser::Serializer for &mut Serializer {
141 type Ok = ();
142 type Error = Error;
143
144 type SerializeSeq = Self;
145 type SerializeTuple = Self;
146 type SerializeTupleStruct = Self;
147 type SerializeTupleVariant = Self;
148 type SerializeMap = Self;
149 type SerializeStruct = Self;
150 type SerializeStructVariant = Self;
151
152 fn serialize_bool(self, v: bool) -> Result<()> {
153 debug!("serialize bool: {}", v);
154 self.output += if v { "true" } else { "false" };
155 Ok(())
156 }
157
158 fn serialize_i8(self, v: i8) -> Result<()> {
159 debug!("serialize i8: {}", v);
160 self.serialize_i64(i64::from(v))
161 }
162
163 fn serialize_i16(self, v: i16) -> Result<()> {
164 debug!("serialize i16: {}", v);
165 self.serialize_i64(i64::from(v))
166 }
167
168 fn serialize_i32(self, v: i32) -> Result<()> {
169 debug!("serialize i32: {}", v);
170 self.serialize_i64(i64::from(v))
171 }
172
173 fn serialize_i64(self, v: i64) -> Result<()> {
174 debug!("serialize i64: {}", v);
175 self.output += &v.to_string();
176 Ok(())
177 }
178
179 fn serialize_u8(self, v: u8) -> Result<()> {
180 debug!("serialize u8: {}", v);
181 self.serialize_u64(u64::from(v))
182 }
183
184 fn serialize_u16(self, v: u16) -> Result<()> {
185 debug!("serialize u16: {}", v);
186 self.serialize_u64(u64::from(v))
187 }
188
189 fn serialize_u32(self, v: u32) -> Result<()> {
190 debug!("serialize u32: {}", v);
191 self.serialize_u64(u64::from(v))
192 }
193
194 fn serialize_u64(self, v: u64) -> Result<()> {
195 debug!("serialize u64: {}", v);
196 self.output += &v.to_string();
197 Ok(())
198 }
199
200 fn serialize_f32(self, v: f32) -> Result<()> {
201 debug!("serialize f32: {}", v);
202 self.serialize_f64(f64::from(v))
203 }
204
205 fn serialize_f64(self, v: f64) -> Result<()> {
206 debug!("serialize f64: {}", v);
207 self.output += &v.to_string();
208 Ok(())
209 }
210
211 fn serialize_char(self, v: char) -> Result<()> {
212 debug!("serialize char: {}", v);
213 self.serialize_str(&v.to_string())
214 }
215
216 fn serialize_str(self, v: &str) -> Result<()> {
217 debug!("serialize &str: {}", v);
218
219 if self.key {
220 let mut key = self.base_prefix.clone();
221 if !self.prefix.is_empty() {
222 self.prefix.push('_');
223 }
224 self.prefix += &v.to_uppercase();
225 key += &self.prefix;
226 if key.find(' ').is_some()
227 || key.find('#').is_some()
228 || key.find('\"').is_some()
229 || key.find('\'').is_some()
230 {
231 return Err(Error::Syntax);
232 }
233
234 self.output += &key;
235 } else if !v.is_empty() {
236 self.output += "\"";
237 self.output += v;
238 self.output += "\"";
239 }
240 Ok(())
241 }
242
243 fn serialize_bytes(self, v: &[u8]) -> Result<()> {
244 debug!("serialize bytes: {:?}", v);
245 self.serialize_str(&String::from_utf8(v.to_vec()).map_err(|_| Error::Syntax)?)
246 }
247
248 fn serialize_none(self) -> Result<()> {
249 debug!("serialize none");
250 self.serialize_unit()
251 }
252
253 fn serialize_some<T>(self, value: &T) -> Result<()>
254 where
255 T: ?Sized + serde::ser::Serialize,
256 {
257 debug!("serialize some");
258 value.serialize(self)
259 }
260
261 fn serialize_unit(self) -> Result<()> {
262 debug!("serialize unit");
263 Ok(())
264 }
265
266 fn serialize_unit_struct(self, _name: &'static str) -> Result<()> {
267 debug!("serialize unit struct: {}", _name);
268 self.serialize_unit()
269 }
270
271 fn serialize_unit_variant(
272 self,
273 _name: &'static str,
274 _variant_index: u32,
275 variant: &'static str,
276 ) -> Result<()> {
277 debug!("serialize unit variant: {}", variant);
278 self.serialize_str(variant)
279 }
280
281 fn serialize_newtype_struct<T>(self, _name: &'static str, value: &T) -> Result<()>
282 where
283 T: ?Sized + serde::ser::Serialize,
284 {
285 debug!("serialize newtype struct: {}", _name);
286 value.serialize(self)
287 }
288
289 fn serialize_newtype_variant<T>(
290 self,
291 _name: &'static str,
292 _variant_index: u32,
293 variant: &'static str,
294 value: &T,
295 ) -> Result<()>
296 where
297 T: ?Sized + serde::ser::Serialize,
298 {
299 debug!("serialize newtype struct variant: {}", variant);
300 if self.sequence {
301 return value.serialize(&mut *self);
302 }
303
304 self.key = true;
305 variant.serialize(&mut *self)?;
306 self.key = false;
307 self.output += "=";
308 value.serialize(&mut *self)?;
309 self.output += "\n";
310 Ok(())
311 }
312
313 fn serialize_seq(self, _len: Option<usize>) -> Result<Self::SerializeSeq> {
314 debug!("serialize sequence");
315 if self.sequence {
316 return Err(Error::UnsupportedStructureInSeq);
317 }
318 self.sequence = true;
319 Ok(self)
320 }
321
322 fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> {
323 debug!("serialize tuple");
324 self.serialize_seq(Some(len))
325 }
326
327 fn serialize_tuple_struct(
328 self,
329 _name: &'static str,
330 len: usize,
331 ) -> Result<Self::SerializeTupleStruct> {
332 debug!("serialize tuple struct");
333 self.serialize_seq(Some(len))
334 }
335
336 fn serialize_tuple_variant(
337 self,
338 _name: &'static str,
339 _variant_index: u32,
340 _variant: &'static str,
341 _len: usize,
342 ) -> Result<Self::SerializeTupleVariant> {
343 debug!("serialize tuple variant");
344 Ok(self)
345 }
346
347 fn serialize_map(self, _len: Option<usize>) -> Result<Self::SerializeMap> {
348 debug!("serialize map");
349 if self.sequence {
350 return Err(Error::UnsupportedStructureInSeq);
351 }
352 Ok(self)
353 }
354
355 fn serialize_struct(self, _name: &'static str, len: usize) -> Result<Self::SerializeStruct> {
356 debug!("serialize struct: {}", _name);
357 self.serialize_map(Some(len))
358 }
359
360 fn serialize_struct_variant(
361 self,
362 _name: &'static str,
363 _variant_index: u32,
364 _variant: &'static str,
365 len: usize,
366 ) -> Result<Self::SerializeStructVariant> {
367 debug!("serialize struct variant: {}/{}", _name, _variant);
368 self.serialize_map(Some(len))
369 }
370}
371
372impl serde::ser::SerializeSeq for &mut Serializer {
373 type Ok = ();
374 type Error = Error;
375
376 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
377 where
378 T: ?Sized + serde::ser::Serialize,
379 {
380 debug!("serializing sequence element");
381 let r = value.serialize(&mut **self);
382 self.output += ",";
383 r
384 }
385
386 fn end(self) -> Result<()> {
387 debug!("ended serializing sequence element");
388 self.output.pop();
389 self.sequence = false;
390 self.strip_line_breaks();
391 Ok(())
392 }
393}
394
395impl serde::ser::SerializeTuple for &mut Serializer {
396 type Ok = ();
397 type Error = Error;
398
399 fn serialize_element<T>(&mut self, value: &T) -> Result<()>
400 where
401 T: ?Sized + serde::ser::Serialize,
402 {
403 debug!("serialize tuple element");
404 let r = value.serialize(&mut **self);
405 self.output += ",";
406 r
407 }
408
409 fn end(self) -> Result<()> {
410 debug!("ended serializing tuple element");
411 self.output.pop();
412 self.sequence = false;
413 self.strip_line_breaks();
414 Ok(())
415 }
416}
417
418impl serde::ser::SerializeTupleStruct for &mut Serializer {
419 type Ok = ();
420 type Error = Error;
421
422 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
423 where
424 T: ?Sized + serde::ser::Serialize,
425 {
426 debug!("serialize tuple struct field");
427 let r = value.serialize(&mut **self);
428 self.output += ",";
429 r
430 }
431
432 fn end(self) -> Result<()> {
433 debug!("ended serializing tuple struct field");
434 self.output.pop();
435 self.sequence = false;
436 Ok(())
437 }
438}
439
440impl serde::ser::SerializeTupleVariant for &mut Serializer {
441 type Ok = ();
442 type Error = Error;
443
444 fn serialize_field<T>(&mut self, value: &T) -> Result<()>
445 where
446 T: ?Sized + serde::ser::Serialize,
447 {
448 debug!("serialize tuple variant field");
449 let r = value.serialize(&mut **self);
450 self.output += ",";
451 r
452 }
453
454 fn end(self) -> Result<()> {
455 debug!("ended serializing tuple variant field");
456 self.output.pop();
457 self.sequence = false;
458 Ok(())
459 }
460}
461
462impl serde::ser::SerializeMap for &mut Serializer {
463 type Ok = ();
464 type Error = Error;
465
466 fn serialize_key<T>(&mut self, key: &T) -> Result<()>
467 where
468 T: ?Sized + serde::ser::Serialize,
469 {
470 debug!("serialize map key");
471 serialize_map_struct_key(self, key)
472 }
473
474 fn serialize_value<T>(&mut self, value: &T) -> Result<()>
475 where
476 T: ?Sized + serde::ser::Serialize,
477 {
478 debug!("serialize map value");
479 serialize_map_struct_value(self, value)
480 }
481
482 fn end(self) -> Result<()> {
483 debug!("ended serializing map");
484 self.strip_line_breaks();
485 Ok(())
486 }
487}
488
489impl serde::ser::SerializeStruct for &mut Serializer {
490 type Ok = ();
491 type Error = Error;
492
493 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
494 where
495 T: ?Sized + serde::ser::Serialize,
496 {
497 debug!("serializing struct field");
498
499 serialize_field(self, key, value)
500 }
501
502 fn end(self) -> Result<()> {
503 debug!("ended serializing struct field");
504 self.strip_line_breaks();
505 Ok(())
506 }
507}
508
509impl serde::ser::SerializeStructVariant for &mut Serializer {
510 type Ok = ();
511 type Error = Error;
512
513 fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<()>
514 where
515 T: ?Sized + serde::ser::Serialize,
516 {
517 debug!("serializing struct variant field");
518
519 serialize_field(self, key, value)
520 }
521
522 fn end(self) -> Result<()> {
523 debug!("ended serializing struct variant");
524 self.strip_line_breaks();
525 Ok(())
526 }
527}
528
529fn serialize_field<T>(ser: &'_ mut &'_ mut Serializer, key: &'static str, value: &T) -> Result<()>
530where
531 T: ?Sized + serde::ser::Serialize,
532{
533 serialize_map_struct_key(ser, key)?;
534 serialize_map_struct_value::<T>(ser, value)?;
535 Ok(())
536}
537
538fn serialize_map_struct_key<T>(ser: &'_ mut &'_ mut Serializer, key: &T) -> Result<()>
539where
540 T: ?Sized + serde::ser::Serialize,
541{
542 if ser.sequence {
543 return Err(Error::UnsupportedStructureInSeq);
544 }
545
546 ser.prefix_before = ser.prefix.clone();
547
548 let prefix = format!("{}{}", ser.prefix, '=');
549 if ser.output.ends_with(&prefix) {
550 ser.output = ser.output[..ser.output.len() - prefix.len()].into();
551 }
552
553 ser.key = true;
554 key.serialize(&mut **ser)?;
555 ser.key = false;
556 Ok(())
557}
558
559fn serialize_map_struct_value<T>(ser: &'_ mut &'_ mut Serializer, value: &T) -> Result<()>
560where
561 T: ?Sized + serde::ser::Serialize,
562{
563 if ser.sequence {
564 return Err(Error::UnsupportedStructureInSeq);
565 }
566
567 ser.output += "=";
568 value.serialize(&mut **ser)?;
569 ser.output += "\n";
570
571 ser.prefix = ser.prefix_before.clone();
572 Ok(())
573}
574
575#[cfg(test)]
576mod tests {
577 use std::{collections::HashMap, io::Cursor};
578
579 use super::{to_file, to_string, to_writer};
580 use crate::{Value, from_str};
581
582 #[test]
583 fn serialize_to_string_value() {
584 let env = Value::from_iter([("hello", "WORLD")]);
587
588 let output = to_string(&env).expect("Failed to serialize to string");
590
591 let expected = "HELLO=\"WORLD\"";
593 assert_eq!(expected, &output);
594
595 let deserialized = from_str::<Value>(&output).expect("Failed to deserialize to value");
597 assert_eq!(deserialized, env);
598 }
599
600 #[test]
601 fn serialize_to_string_struct() {
602 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
604 struct StructTestNested {
605 c: u8,
606 }
607
608 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
609 struct StructTest {
610 a: u8,
611 b: StructTestNested,
612 }
613
614 let env = StructTest {
615 a: 1,
616 b: StructTestNested { c: 2 },
617 };
618
619 let output = to_string(&env).expect("Failed to serialize to string");
621
622 assert_eq!("A=1\nB_C=2", output);
624 }
625
626 #[test]
627 fn serialize_to_string_sequence() {
628 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
631 struct SeqTest {
632 a: Vec<String>,
633 b: String,
634 }
635
636 let env = SeqTest {
637 a: vec!["HELLO".into(), "WORLD".into()],
638 b: "control value".into(),
639 };
640
641 let output = to_string(&env).expect("Failed to serialize to string");
643
644 let expected = "A=\"HELLO\",\"WORLD\"\nB=\"control value\"";
646 assert_eq!(expected, &output);
647
648 let deserialized = from_str::<SeqTest>(&output).expect("Failed to deserialize to struct");
650 assert_eq!(deserialized, env);
651 }
652
653 #[test]
654 fn serialize_to_string_enum() {
655 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
657 enum EnumTestEnum {
658 HELLO,
659 WORLD,
660 }
661
662 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
663 struct EnumTest {
664 a: EnumTestEnum,
665 }
666
667 let env = EnumTest {
668 a: EnumTestEnum::HELLO,
669 };
670
671 let output = to_string(&env).expect("Failed to serialize to string");
673
674 let expected = "A=\"HELLO\"";
676 assert_eq!(expected, &output);
677
678 let deserialized = from_str::<EnumTest>(&output).expect("Failed to deserialize to struct");
680 assert_eq!(deserialized, env);
681 }
682
683 #[test]
684 fn serialize_to_string_numbers() {
685 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
687 struct NumberTest {
688 u8: u8,
689 u16: u16,
690 u32: u32,
691 u64: u64,
692 i8: i8,
693 i16: i16,
694 i32: i32,
695 i64: i64,
696 f32: f32,
697 f64: f64,
698 usize: usize,
699 }
700
701 let env = NumberTest {
702 u8: 255,
703 u16: 65535,
704 u32: 4294967295,
705 u64: 18446744073709551615,
706 i8: -128,
707 i16: -32768,
708 i32: -2147483648,
709 i64: -9223372036854775808,
710 f32: -3.5,
711 f64: 3.5,
712 usize: 18446744073709551615,
713 };
714
715 let output = to_string(&env).expect("Failed to serialize to string");
717
718 let expected = "U8=255\nU16=65535\nU32=4294967295\nU64=18446744073709551615\nI8=-128\nI16=-32768\nI32=-2147483648\nI64=-9223372036854775808\nF32=-3.5\nF64=3.5\nUSIZE=18446744073709551615";
720 assert_eq!(expected, &output);
721
722 let deserialized = from_str::<NumberTest>(&output).expect("Failed to deserialize to struct");
724 assert_eq!(deserialized, env);
725 }
726
727 #[test]
728 fn serialize_to_string_bool() {
729 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
731 struct BoolTest {
732 a: bool,
733 b: bool,
734 }
735
736 let env = BoolTest { a: true, b: false };
737
738 let output = to_string(&env).expect("Failed to serialize to string");
740
741 let expected = "A=true\nB=false";
743 assert_eq!(expected, &output);
744
745 let deserialized = from_str::<BoolTest>(&output).expect("Failed to deserialize to struct");
747 assert_eq!(deserialized, env);
748 }
749
750 #[test]
751 fn serialize_to_string_option() {
752 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
754 struct OptionTest {
755 a: Option<String>,
756 b: Option<String>,
757 }
758
759 let env = OptionTest {
760 a: Some("HELLO".into()),
761 b: None,
762 };
763
764 let output = to_string(&env).expect("Failed to serialize to string");
766
767 let expected = "A=\"HELLO\"\nB=";
769 assert_eq!(expected, &output);
770
771 let deserialized = from_str::<OptionTest>(&output).expect("Failed to deserialize to struct");
774 assert_eq!(deserialized.a, env.a);
775 }
776
777 #[test]
778 fn serialize_to_string_hashmap() {
779 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
781 struct MapTest {
782 #[serde(flatten)]
783 inner: HashMap<String, String>,
784 }
785
786 let mut env = MapTest {
787 inner: HashMap::new(),
788 };
789 env.inner.insert("hello".into(), "WORLD".into());
790
791 let output = to_string(&env).expect("Failed to serialize to string");
793
794 let expected = "HELLO=\"WORLD\"";
796 assert_eq!(expected, &output);
797
798 let deserialized = from_str::<MapTest>(&output).expect("Failed to deserialize to struct");
800 assert_eq!(deserialized, env);
801 }
802
803 #[test]
804 fn serialize_to_string_nested_hashmap() {
805 #[derive(Debug, PartialEq, serde::Serialize, serde::Deserialize)]
807 struct NestedMapTest {
808 inner: HashMap<String, String>,
809 }
810
811 let env = NestedMapTest {
812 inner: HashMap::from([("HELLO".into(), "WORLD".into())]),
813 };
814
815 let output = to_string(&env).expect("Failed to serialize to string");
817
818 let expected = "INNER_HELLO=\"WORLD\"";
820 assert_eq!(expected, &output);
821 }
822
823 #[test]
824 fn serialize_to_writer() {
825 let env = Value::from_iter([("HELLO", "WORLD")]);
827
828 let mut writer = Cursor::new(Vec::new());
829
830 to_writer(&mut writer, &env).expect("Failed to serialize to writer");
832
833 let expected_output = "HELLO=\"WORLD\"";
835 let output = String::from_utf8(writer.into_inner()).expect("Invalid UTF-8 sequence");
836 assert_eq!(expected_output, output);
837 }
838
839 #[test]
840 fn serialize_to_file() {
841 let env = Value::from_iter([("HELLO", "WORLD")]);
843
844 let file = tempfile::NamedTempFile::new_in(std::env::temp_dir()).expect("Failed to create temp file");
846
847 to_file(&file.path(), &env).expect("Failed to serialize to file");
849
850 let expected_output = "HELLO=\"WORLD\"";
852 let output = std::fs::read_to_string(file.path()).expect("Failed to read file");
853 assert_eq!(expected_output, output);
854 }
855}