1use super::{Diagnostic, PackageId, Target};
2use camino::Utf8PathBuf;
3#[cfg(feature = "builder")]
4use derive_builder::Builder;
5use serde::{Deserialize, Serialize};
6use std::fmt;
7use std::io::{self, BufRead, Read};
8
9#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
12#[cfg_attr(feature = "builder", derive(Builder))]
13#[non_exhaustive]
14#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
15pub struct ArtifactProfile {
16 pub opt_level: String,
18 pub debuginfo: Option<u32>,
20 pub debug_assertions: bool,
23 pub overflow_checks: bool,
25 pub test: bool,
27}
28
29#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
31#[cfg_attr(feature = "builder", derive(Builder))]
32#[non_exhaustive]
33#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
34pub struct Artifact {
35 pub package_id: PackageId,
37 #[serde(default)]
39 pub manifest_path: Utf8PathBuf,
40 pub target: Target,
42 pub profile: ArtifactProfile,
44 pub features: Vec<String>,
46 pub filenames: Vec<Utf8PathBuf>,
49 pub executable: Option<Utf8PathBuf>,
51 pub fresh: bool,
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
58#[cfg_attr(feature = "builder", derive(Builder))]
59#[non_exhaustive]
60#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
61pub struct CompilerMessage {
62 pub package_id: PackageId,
64 pub target: Target,
66 pub message: Diagnostic,
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
72#[cfg_attr(feature = "builder", derive(Builder))]
73#[non_exhaustive]
74#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
75pub struct BuildScript {
76 pub package_id: PackageId,
78 pub linked_libs: Vec<Utf8PathBuf>,
80 pub linked_paths: Vec<Utf8PathBuf>,
82 pub cfgs: Vec<String>,
84 pub env: Vec<(String, String)>,
86 #[serde(default)]
90 pub out_dir: Utf8PathBuf,
91}
92
93#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
95#[cfg_attr(feature = "builder", derive(Builder))]
96#[non_exhaustive]
97#[cfg_attr(feature = "builder", builder(pattern = "owned", setter(into)))]
98pub struct BuildFinished {
99 pub success: bool,
101}
102
103#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
105#[non_exhaustive]
106#[serde(tag = "reason", rename_all = "kebab-case")]
107pub enum Message {
108 CompilerArtifact(Artifact),
110 CompilerMessage(CompilerMessage),
112 BuildScriptExecuted(BuildScript),
114 BuildFinished(BuildFinished),
119 #[serde(skip)]
122 TextLine(String),
123}
124
125impl Message {
126 pub fn parse_stream<R: Read>(input: R) -> MessageIter<R> {
129 MessageIter { input }
130 }
131}
132
133impl fmt::Display for CompilerMessage {
134 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
135 write!(f, "{}", self.message)
136 }
137}
138
139pub struct MessageIter<R> {
141 input: R,
142}
143
144impl<R: BufRead> Iterator for MessageIter<R> {
145 type Item = io::Result<Message>;
146 fn next(&mut self) -> Option<Self::Item> {
147 let mut line = String::new();
148 self.input
149 .read_line(&mut line)
150 .map(|n| {
151 if n == 0 {
152 None
153 } else {
154 if line.ends_with('\n') {
155 line.truncate(line.len() - 1);
156 }
157 let mut deserializer = serde_json::Deserializer::from_str(&line);
158 deserializer.disable_recursion_limit();
159 Some(Message::deserialize(&mut deserializer).unwrap_or(Message::TextLine(line)))
160 }
161 })
162 .transpose()
163 }
164}
165
166type MessageIterator<R> =
168 serde_json::StreamDeserializer<'static, serde_json::de::IoRead<R>, Message>;
169
170#[deprecated(note = "Use Message::parse_stream instead")]
173pub fn parse_messages<R: Read>(input: R) -> MessageIterator<R> {
174 serde_json::Deserializer::from_reader(input).into_iter::<Message>()
175}