1use std::{io, string::FromUtf8Error};
2
3use crate::{data::DataType, format::Indentation};
4use colored_json::ColoredFormatter;
5use serde::Serialize;
6use serde_json::{
7 ser::{CompactFormatter, Formatter, PrettyFormatter},
8 Serializer, Value,
9};
10use thiserror::Error;
11
12#[derive(Debug, Error)]
13pub enum Error {
14 #[error("error while formatting json: {0}")]
15 Json(#[from] serde_json::Error),
16
17 #[error("error while formatting yaml: {0}")]
18 Yaml(#[from] serde_yaml::Error),
19
20 #[error("IO error while formatting: {0}")]
21 Io(#[from] io::Error),
22
23 #[error("error while creating String from UTF-8 bytes: {0}")]
24 FromUtf8(#[from] FromUtf8Error),
25}
26
27pub type Result<T> = std::result::Result<T, Error>;
28
29impl DataType {
30 pub fn pretty_format(&self, value: &Value, indentation: Indentation) -> Result<String> {
31 let mut buf = Vec::new();
32 self.pretty_format_to_writer(&mut buf, value, indentation)?;
33 Ok(String::from_utf8(buf)?)
34 }
35
36 pub fn pretty_format_to_writer<W: io::Write>(
37 &self,
38 writer: &mut W,
39 value: &Value,
40 indentation: Indentation,
41 ) -> Result<()> {
42 match self {
43 DataType::Json => serialize_json(writer, value, indentation),
44 DataType::Yaml => Ok(serde_yaml::to_writer(writer, value)?),
46 }
47 }
48}
49
50impl DataType {
51 pub fn pretty_format_colored(&self, value: &Value, indentation: Indentation) -> Result<String> {
52 let mut buf = Vec::new();
53 self.pretty_format_colored_to_writer(&mut buf, value, indentation)?;
54 Ok(String::from_utf8(buf)?)
55 }
56
57 pub fn pretty_format_colored_to_writer<W: io::Write>(
58 &self,
59 writer: &mut W,
60 value: &Value,
61 indentation: Indentation,
62 ) -> Result<()> {
63 match self {
64 DataType::Json => serialize_colored_json(value, writer, indentation),
65 DataType::Yaml => Ok(serde_yaml::to_writer(writer, value)?),
67 }
68 }
69}
70
71fn serialize_json<W: io::Write>(
72 writer: &mut W,
73 value: &Value,
74 indentation: Indentation,
75) -> Result<()> {
76 match indentation {
77 Indentation::None => {
78 let formatter = CompactFormatter {};
79 serialize_json_with_formatter(value, writer, formatter)
80 }
81 Indentation::Spaces(_) | Indentation::Tabs(_) => {
82 let indentation_fmt = indentation.to_string();
83 let formatter = PrettyFormatter::with_indent(indentation_fmt.as_bytes());
84 serialize_json_with_formatter(value, writer, formatter)
85 }
86 }
87}
88
89fn serialize_colored_json<W: io::Write>(
90 value: &Value,
91 writer: &mut W,
92 indentation: Indentation,
93) -> Result<()> {
94 let indentation_fmt = indentation.to_string();
95 match indentation {
96 Indentation::None => {
97 let formatter = ColoredFormatter::new(CompactFormatter {});
98 serialize_json_with_formatter(value, writer, formatter)
99 }
100 Indentation::Spaces(_) | Indentation::Tabs(_) => {
101 let formatter =
102 ColoredFormatter::new(PrettyFormatter::with_indent(indentation_fmt.as_bytes()));
103 serialize_json_with_formatter(value, writer, formatter)
104 }
105 }
106}
107
108fn serialize_json_with_formatter<W: io::Write, F: Formatter>(
109 value: &Value,
110 writer: &mut W,
111 formatter: F,
112) -> Result<()> {
113 let mut serializer = Serializer::with_formatter(writer, formatter);
114 Ok(value.serialize(&mut serializer)?)
115}