messagepack_cli/
conversion.rs

1//! Conversion implementation. Executes conversion from a Reader to a Writer.
2
3use std::{
4	fmt::Debug,
5	io::{Read, Write},
6};
7
8use error_stack::{report, Report, ResultExt};
9use rmp_serde::config::{DefaultConfig, StructMapConfig};
10use serde_json::ser::PrettyFormatter;
11
12use crate::Error;
13
14/// Direction of conversion.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub enum ConversionDirection {
17	/// Automatic detection of the input.
18	Auto,
19	/// Convert MsgPack to JSON.
20	MsgPack2Json,
21	/// Convert JSON to MsgPack.
22	Json2MsgPack,
23}
24
25/// Converter instance, owning a [`Read`]er and a [`Write`]r to input and output
26/// the data.
27pub struct Converter<I, O> {
28	/// Source of input data.
29	input: I,
30	/// Sink of output data.
31	output: O,
32	/// Direction of conversion.
33	direction: ConversionDirection,
34}
35
36impl<I, O> Converter<I, O>
37where
38	I: Read,
39	O: Write,
40{
41	/// Create new converter instance given input, output and conversion
42	/// direction.
43	#[must_use]
44	pub fn new(input: I, output: O, direction: ConversionDirection) -> Self {
45		Self { input, output, direction }
46	}
47
48	/// Execute the conversion.
49	pub fn execute(mut self) -> Result<(), Report<Error>> {
50		match self.direction {
51			ConversionDirection::Auto => self.automatic_conversion()?,
52			ConversionDirection::MsgPack2Json => {
53				let mut deserializer = msgpack_deserializer(self.input);
54				let mut serializer = json_serializer(&mut self.output);
55				serde_transcode::transcode(&mut deserializer, &mut serializer)
56					.change_context(Error::Transcoding)?;
57			}
58			ConversionDirection::Json2MsgPack => {
59				let mut deserializer = json_deserializer(self.input);
60				let mut serializer = msgpack_serializer(&mut self.output);
61				serde_transcode::transcode(&mut deserializer, &mut serializer)
62					.change_context(Error::Transcoding)?;
63			}
64		}
65		self.output.write(&[b'\n']).change_context(Error::FileWrite)?;
66		Ok(())
67	}
68
69	/// Execute automatically detected conversion. This reads the full input
70	/// until the end and attempts to transcode JSON to MsgPack first, then try
71	/// the other way if it did not work.
72	fn automatic_conversion(&mut self) -> Result<(), Report<Error>> {
73		let mut data = Vec::new();
74		self.input.read_to_end(&mut data).change_context(Error::FileRead)?;
75		let mut error = report!(Error::AutomaticDetection);
76
77		// Try JSON to MsgPack first.
78		let mut output = Vec::new();
79		let mut deserializer = json_deserializer(data.as_slice());
80		let mut serializer = msgpack_serializer(&mut output);
81		let res = serde_transcode::transcode(&mut deserializer, &mut serializer)
82			.change_context(Error::Transcoding);
83		match res {
84			Ok(_) => return self.output.write_all(&output).change_context(Error::FileWrite),
85			Err(err) => error.extend_one(err),
86		}
87		drop(output); // Drop, we will write directly to the output, otherwise we would clear it.
88
89		// It did not work, try MsgPack to JSON now.
90		let mut deserializer = msgpack_deserializer(data.as_slice());
91		let mut serializer = json_serializer(&mut self.output);
92		let res = serde_transcode::transcode(&mut deserializer, &mut serializer)
93			.change_context(Error::Transcoding);
94		match res {
95			Ok(_) => return Ok(()),
96			Err(err) => error.extend_one(err),
97		}
98
99		// This didn't work either, return the error.
100		Err(error)
101	}
102}
103
104/// Construct a MsgPack Deserializer.
105fn msgpack_deserializer<R: Read>(
106	reader: R,
107) -> rmp_serde::Deserializer<rmp_serde::decode::ReadReader<R>> {
108	rmp_serde::Deserializer::new(reader)
109}
110
111/// Construct a MsgPack Serializer.
112fn msgpack_serializer<W: Write>(
113	writer: W,
114) -> rmp_serde::Serializer<W, StructMapConfig<DefaultConfig>> {
115	rmp_serde::Serializer::new(writer).with_struct_map()
116}
117
118/// Construct a JSON Deserializer.
119fn json_deserializer<R: Read>(reader: R) -> serde_json::Deserializer<serde_json::de::IoRead<R>> {
120	serde_json::Deserializer::from_reader(reader)
121}
122
123/// Construct a JSON Serializer.
124fn json_serializer<W: Write>(writer: W) -> serde_json::Serializer<W, PrettyFormatter<'static>> {
125	serde_json::Serializer::pretty(writer)
126}
127
128impl<I, O> Debug for Converter<I, O> {
129	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
130		f.debug_struct("Converter")
131			.field("input", &"<redacted>")
132			.field("output", &"<redacted>")
133			.field("direction", &self.direction)
134			.finish()
135	}
136}