1- use std:: fmt:: Display ;
1+ use std:: { borrow :: Cow , fmt:: Display } ;
22
3+ use derivative:: Derivative ;
34use miette:: Diagnostic ;
45use once_cell:: sync:: OnceCell ;
56use thiserror:: Error ;
@@ -11,12 +12,12 @@ use crate::Error;
1112#[ error( "{err}" ) ]
1213pub ( crate ) struct WithHelp {
1314 err : Error ,
14- help : Option < String > ,
15- wrap_help : OnceCell < Option < String > > ,
15+ help : Option < Cow < ' static , str > > ,
16+ wrap_help : OnceCell < Option < Cow < ' static , str > > > ,
1617}
1718
1819impl WithHelp {
19- pub ( crate ) fn with_help ( mut self , help : impl Into < String > ) -> Self {
20+ pub ( crate ) fn with_help ( mut self , help : impl Into < Cow < ' static , str > > ) -> Self {
2021 self . help = Some ( help. into ( ) ) ;
2122 self
2223 }
@@ -54,12 +55,12 @@ impl miette::Diagnostic for WithHelp {
5455 fn help < ' a > ( & ' a self ) -> Option < Box < dyn Display + ' a > > {
5556 let help = self . wrap_help . get_or_init ( || {
5657 let prev = self . err . help ( ) . map ( |h| h. to_string ( ) ) ;
57- let help = self . help . as_ref ( ) . map ( |h| h . to_string ( ) ) ;
58+ let help = self . help . as_ref ( ) . cloned ( ) ;
5859 if let Some ( prev) = prev {
59- if let Some ( help) = help {
60- Some ( format ! ( "{prev}\n {help}" ) )
60+ if let Some ( help) = & help {
61+ Some ( format ! ( "{prev}\n {help}" ) . into ( ) )
6162 } else {
62- Some ( prev)
63+ Some ( prev. into ( ) )
6364 }
6465 } else if help. is_some ( ) {
6566 help
@@ -91,3 +92,76 @@ impl miette::Diagnostic for WithHelp {
9192 self . err . diagnostic_source ( )
9293 }
9394}
95+
96+ /// Wrap diagnostic with label.
97+ #[ derive( Error , Derivative ) ]
98+ #[ derivative( Debug ) ]
99+ #[ error( "{err}" ) ]
100+ pub ( crate ) struct WithLabel {
101+ err : Error ,
102+ #[ derivative( Debug = "ignore" ) ]
103+ labels : Option < Vec < miette:: LabeledSpan > > ,
104+ }
105+
106+ impl WithLabel {
107+ pub ( crate ) fn with_label ( mut self , labels : impl Iterator < Item = miette:: LabeledSpan > ) -> Self {
108+ self . labels = Some ( labels. collect ( ) ) ;
109+ self
110+ }
111+ }
112+
113+ impl From < Box < dyn Diagnostic + Send + Sync > > for WithLabel {
114+ fn from ( value : Box < dyn Diagnostic + Send + Sync > ) -> Self {
115+ Self {
116+ err : Error :: new_boxed ( value) ,
117+ labels : None ,
118+ }
119+ }
120+ }
121+
122+ impl From < Error > for WithLabel {
123+ fn from ( value : Error ) -> Self {
124+ Self {
125+ err : value,
126+ labels : None ,
127+ }
128+ }
129+ }
130+
131+ impl miette:: Diagnostic for WithLabel {
132+ fn code < ' a > ( & ' a self ) -> Option < Box < dyn Display + ' a > > {
133+ self . err . code ( )
134+ }
135+
136+ fn severity ( & self ) -> Option < miette:: Severity > {
137+ self . err . severity ( )
138+ }
139+
140+ fn help < ' a > ( & ' a self ) -> Option < Box < dyn Display + ' a > > {
141+ self . err . help ( )
142+ }
143+
144+ fn url < ' a > ( & ' a self ) -> Option < Box < dyn Display + ' a > > {
145+ self . err . url ( )
146+ }
147+
148+ fn source_code ( & self ) -> Option < & dyn miette:: SourceCode > {
149+ self . err . source_code ( )
150+ }
151+
152+ fn labels ( & self ) -> Option < Box < dyn Iterator < Item = miette:: LabeledSpan > + ' _ > > {
153+ self
154+ . labels
155+ . as_ref ( )
156+ . cloned ( )
157+ . map ( |l| Box :: new ( l. into_iter ( ) ) as Box < dyn Iterator < Item = miette:: LabeledSpan > > )
158+ }
159+
160+ fn related < ' a > ( & ' a self ) -> Option < Box < dyn Iterator < Item = & ' a dyn miette:: Diagnostic > + ' a > > {
161+ self . err . related ( )
162+ }
163+
164+ fn diagnostic_source ( & self ) -> Option < & dyn Diagnostic > {
165+ self . err . diagnostic_source ( )
166+ }
167+ }
0 commit comments