1use std::convert::Infallible;
2use std::fmt::{Debug, Display, Formatter};
3use std::io;
4use std::num::ParseIntError;
5use std::ops::Range;
6use std::rc::Rc;
7use std::string::FromUtf8Error;
8use std::sync::{Arc, PoisonError};
9
10use nom::error::VerboseError;
11use nom::Err;
12use nom_locate::LocatedSpan;
13use nom_supreme::error::{ErrorTree, StackContext};
14use serde::de::Error;
15use tokio::sync::mpsc::error::{SendError, SendTimeoutError};
16use tokio::sync::oneshot::error::RecvError;
17use tokio::time::error::Elapsed;
18
19use crate::err::report::{Label, Report, ReportKind};
20use cosmic_nom::Span;
21use cosmic_nom::SpanExtra;
22
23use crate::parse::error::find_parse_err;
24use crate::substance::{FormErrs, Substance};
25use crate::wave::core::http2::StatusCode;
26use crate::wave::core::ReflectedCore;
27use serde::{Deserialize, Serialize};
28
29#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
30pub enum SpaceErr {
31 Status { status: u16, message: String },
32 ParseErrs(ParseErrs),
33}
34
35impl SpaceErr {
36 pub fn print(&self) {
37 match self {
38 SpaceErr::Status { status, message } => {
39 println!("{}: {}", status, message);
40 }
41 SpaceErr::ParseErrs(errs) => {
42 println!("REport len: {}", errs.report.len());
43 for report in &errs.report {
44 let report: ariadne::Report = report.clone().into();
45 if let Some(source) = &errs.source {
46 let source = source.to_string();
47 report.print(ariadne::Source::from(source));
48 } else {
49 println!("No source..");
50 }
51 }
52 }
53 }
54 }
55}
56
57impl Into<ReflectedCore> for SpaceErr {
58 fn into(self) -> ReflectedCore {
59 println!("SpaceErr -> ReflectedCore");
60 match self {
61 SpaceErr::Status { status, .. } => ReflectedCore {
62 headers: Default::default(),
63 status: StatusCode::from_u16(status).unwrap_or(StatusCode::from_u16(500).unwrap()),
64 body: Substance::Err(self),
65 },
66 SpaceErr::ParseErrs(_) => ReflectedCore {
67 headers: Default::default(),
68 status: StatusCode::from_u16(500u16).unwrap_or(StatusCode::from_u16(500).unwrap()),
69 body: Substance::Err(self),
70 },
71 }
72 }
73}
74
75pub trait CoreReflector {
76 fn as_reflected_core(self) -> ReflectedCore;
77}
78
79impl CoreReflector for SpaceErr {
80 fn as_reflected_core(self) -> ReflectedCore {
81 ReflectedCore {
82 headers: Default::default(),
83 status: StatusCode::from_u16(self.status()).unwrap(),
84 body: Substance::Err(self),
85 }
86 }
87}
88
89impl SpaceErr {
90 pub fn str<S: ToString>(s: S) -> SpaceErr {
91 SpaceErr::new(500, s)
92 }
93
94 pub fn map<S>(s: S) -> Self
95 where
96 S: ToString,
97 {
98 SpaceErr::new(500, s)
99 }
100
101 pub fn from_status(status: u16) -> SpaceErr {
102 let message = match status {
103 400 => "Bad Request".to_string(),
104 404 => "Not Found".to_string(),
105 403 => "Forbidden".to_string(),
106 408 => "Timeout".to_string(),
107 500 => "Internal Server Error".to_string(),
108 status => format!("{} Error", status),
109 };
110 SpaceErr::Status { status, message }
111 }
112}
113
114impl SpaceErr {
135 pub fn timeout<S: ToString>(s: S) -> Self {
136 SpaceErr::new(408, format!("Timeout: {}", s.to_string()))
137 }
138
139 pub fn server_error<S: ToString>(s: S) -> Self {
140 SpaceErr::new(500, format!("Server Side Error: {}", s.to_string()))
141 }
142 pub fn forbidden<S: ToString>(s: S) -> Self {
143 SpaceErr::new(403, format!("Forbidden: {}", s.to_string()))
144 }
145
146 pub fn not_found<S: ToString>(s: S) -> Self {
147 SpaceErr::new(404, format!("Not Found: {}", s.to_string()))
148 }
149
150 pub fn bad_request<S: ToString>(s: S) -> Self {
151 SpaceErr::new(400, format!("Bad Request: {}", s.to_string()))
152 }
153
154 pub fn ctx<S: ToString>(mut self, ctx: S) -> Self {
155 match self {
156 Self::Status { status, message } => Self::Status {
157 status,
158 message: format!("{} | {}", message, ctx.to_string()),
159 },
160 Self::ParseErrs(mut errs) => Self::ParseErrs(errs.ctx(ctx)),
161 }
162 }
163}
164
165impl SpaceErr {
166 pub fn new<S: ToString>(status: u16, message: S) -> Self {
167 if message.to_string().as_str() == "500" {
168 panic!("500 err message");
169 }
170
171 Self::Status {
172 status,
173 message: message.to_string(),
174 }
175 }
176}
177
178impl StatusErr for SpaceErr {
179 fn status(&self) -> u16 {
180 match self {
181 SpaceErr::Status { status, .. } => status.clone(),
182 SpaceErr::ParseErrs(_) => 500u16,
183 }
184 }
185
186 fn message(&self) -> String {
187 match self {
188 SpaceErr::Status { status, message } => message.clone(),
189 SpaceErr::ParseErrs(_) => "Error report".to_string(),
190 }
191 }
192}
193
194pub trait StatusErr {
195 fn status(&self) -> u16;
196 fn message(&self) -> String;
197}
198
199impl Display for SpaceErr {
200 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
201 match self {
202 SpaceErr::Status { status, message } => {
203 f.write_str(format!("{}: {}", status, message).as_str())
204 }
205 SpaceErr::ParseErrs(errs) => {
206 println!("PRINING!");
207 self.print();
208 f.write_str("Error Report...")
209 }
210 }
211 }
212}
213
214impl std::error::Error for SpaceErr {}
215
216impl<C> From<SendTimeoutError<C>> for SpaceErr {
217 fn from(e: SendTimeoutError<C>) -> Self {
218 SpaceErr::Status {
219 status: 500,
220 message: e.to_string(),
221 }
222 }
223}
224
225impl<C> From<tokio::sync::mpsc::error::SendError<C>> for SpaceErr {
226 fn from(e: SendError<C>) -> Self {
227 SpaceErr::server_error(e.to_string())
228 }
229}
230
231impl<C> From<tokio::sync::broadcast::error::SendError<C>> for SpaceErr {
232 fn from(e: tokio::sync::broadcast::error::SendError<C>) -> Self {
233 SpaceErr::server_error(e.to_string())
234 }
235}
236
237impl From<tokio::sync::watch::error::RecvError> for SpaceErr {
238 fn from(e: tokio::sync::watch::error::RecvError) -> Self {
239 SpaceErr::server_error(e.to_string())
240 }
241}
242
243impl From<String> for SpaceErr {
244 fn from(message: String) -> Self {
245 Self::Status {
246 status: 500,
247 message,
248 }
249 }
250}
251
252impl From<Elapsed> for SpaceErr {
253 fn from(e: Elapsed) -> Self {
254 Self::Status {
255 status: 408,
256 message: e.to_string(),
257 }
258 }
259}
260
261impl<T> From<PoisonError<T>> for SpaceErr {
262 fn from(e: PoisonError<T>) -> Self {
263 SpaceErr::Status {
264 status: 500,
265 message: e.to_string(),
266 }
267 }
268}
269
270impl From<FromUtf8Error> for SpaceErr {
271 fn from(message: FromUtf8Error) -> Self {
272 Self::Status {
273 status: 500,
274 message: message.to_string(),
275 }
276 }
277}
278
279impl From<&str> for SpaceErr {
280 fn from(message: &str) -> Self {
281 Self::Status {
282 status: 500,
283 message: message.to_string(),
284 }
285 }
286}
287
288impl From<Box<bincode::ErrorKind>> for SpaceErr {
289 fn from(message: Box<bincode::ErrorKind>) -> Self {
290 Self::Status {
291 status: 500,
292 message: message.to_string(),
293 }
294 }
295}
296
297impl From<Infallible> for SpaceErr {
298 fn from(i: Infallible) -> Self {
299 Self::Status {
300 status: 500,
301 message: i.to_string(),
302 }
303 }
304}
305
306impl From<nom::Err<VerboseError<&str>>> for SpaceErr {
307 fn from(error: nom::Err<VerboseError<&str>>) -> Self {
308 Self::Status {
309 status: 500,
310 message: error.to_string(),
311 }
312 }
313}
314
315impl From<semver::Error> for SpaceErr {
316 fn from(error: semver::Error) -> Self {
317 Self::Status {
318 status: 500,
319 message: error.to_string(),
320 }
321 }
322}
323
324impl From<ErrorTree<&str>> for SpaceErr {
325 fn from(error: ErrorTree<&str>) -> Self {
326 Self::Status {
327 status: 500,
328 message: error.to_string(),
329 }
330 }
331}
332
333impl From<strum::ParseError> for SpaceErr {
334 fn from(error: strum::ParseError) -> Self {
335 Self::Status {
336 status: 500,
337 message: error.to_string(),
338 }
339 }
340}
341
342impl From<()> for SpaceErr {
343 fn from(err: ()) -> Self {
344 Self::Status {
345 status: 500,
346 message: "Empty Error".to_string(),
347 }
348 }
349}
350
351impl From<tokio::sync::oneshot::error::RecvError> for SpaceErr {
352 fn from(err: RecvError) -> Self {
353 Self::Status {
354 status: 500,
355 message: err.to_string(),
356 }
357 }
358}
359
360impl From<ParseIntError> for SpaceErr {
361 fn from(x: ParseIntError) -> Self {
362 Self::Status {
363 status: 500,
364 message: x.to_string(),
365 }
366 }
367}
368
369impl From<regex::Error> for SpaceErr {
370 fn from(x: regex::Error) -> Self {
371 Self::Status {
372 status: 500,
373 message: x.to_string(),
374 }
375 }
376}
377
378impl<I: Span> From<nom::Err<ErrorTree<I>>> for SpaceErr {
391 fn from(err: Err<ErrorTree<I>>) -> Self {
392 fn handle<I: Span>(err: ErrorTree<I>) -> SpaceErr {
393 match err {
394 ErrorTree::Base {
395 location,
396 kind: _kind,
397 } => SpaceErr::Status {
398 status: 500,
399 message: format!(
400 "parse error line: {} column: {}",
401 location.location_line(),
402 location.get_column()
403 ),
404 },
405 ErrorTree::Stack { base, contexts } => match contexts.first() {
406 None => SpaceErr::Status {
407 status: 500,
408 message: "error, cannot find location".to_string(),
409 },
410 Some((location, _)) => SpaceErr::Status {
411 status: 500,
412 message: format!(
413 "Stack parse error line: {} column: {}",
414 location.location_line(),
415 location.get_column()
416 ),
417 },
418 },
419 ErrorTree::Alt(what) => SpaceErr::Status {
420 status: 500,
421 message: "alt error".to_string(),
422 },
423 }
424 }
425 match err {
426 Err::Incomplete(_) => SpaceErr::Status {
427 status: 500,
428 message: "unexpected incomplete parsing error".to_string(),
429 },
430
431 Err::Error(err) => handle(err),
432 Err::Failure(err) => handle(err),
433 }
434 }
435}
436
437impl Into<String> for SpaceErr {
438 fn into(self) -> String {
439 self.to_string()
440 }
441}
442
443impl From<io::Error> for SpaceErr {
444 fn from(e: io::Error) -> Self {
445 SpaceErr::new(500, e.to_string().as_str())
446 }
447}
448
449impl From<ParseErrs> for SpaceErr {
450 fn from(errs: ParseErrs) -> Self {
451 SpaceErr::ParseErrs(errs)
452 }
453}
454impl<I: Span> From<nom::Err<ErrorTree<I>>> for ParseErrs {
455 fn from(err: Err<ErrorTree<I>>) -> Self {
456 match find_parse_err(&err) {
457 SpaceErr::Status { .. } => ParseErrs {
458 report: vec![],
459 source: None,
460 ctx: "".to_string(),
461 },
462 SpaceErr::ParseErrs(parse_errs) => parse_errs,
463 }
464 }
465}
466
467#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
468pub struct ParseErrs {
469 pub report: Vec<Report>,
470 pub source: Option<Arc<String>>,
471 pub ctx: String,
472}
473
474impl ParseErrs {
475 pub fn ctx<S: ToString>(mut self, ctx: S) -> Self {
476 Self {
477 report: self.report,
478 source: self.source,
479 ctx: ctx.to_string(),
480 }
481 }
482
483 pub fn from_report(report: Report, source: Arc<String>) -> Self {
484 Self {
485 report: vec![report],
486 source: Some(source),
487 ctx: "".to_string(),
488 }
489 }
490
491 pub fn from_loc_span<I: Span>(message: &str, label: &str, span: I) -> SpaceErr {
492 let mut builder = Report::build(ReportKind::Error, (), 23);
493 let report = builder
494 .with_message(message)
495 .with_label(
496 Label::new(span.location_offset()..(span.location_offset() + span.len()))
497 .with_message(label),
498 )
499 .finish();
500 return ParseErrs::from_report(report, span.extra()).into();
501 }
502
503 pub fn from_range(
504 message: &str,
505 label: &str,
506 range: Range<usize>,
507 extra: SpanExtra,
508 ) -> SpaceErr {
509 let mut builder = Report::build(ReportKind::Error, (), 23);
510 let report = builder
511 .with_message(message)
512 .with_label(Label::new(range).with_message(label))
513 .finish();
514 return ParseErrs::from_report(report, extra).into();
515 }
516
517 pub fn from_owned_span<I: Span>(message: &str, label: &str, span: I) -> SpaceErr {
518 let mut builder = Report::build(ReportKind::Error, (), 23);
519 let report = builder
520 .with_message(message)
521 .with_label(
522 Label::new(span.location_offset()..(span.location_offset() + span.len()))
523 .with_message(label),
524 )
525 .finish();
526 return ParseErrs::from_report(report, span.extra()).into();
527 }
528
529 pub fn fold<E: Into<ParseErrs>>(errs: Vec<E>) -> ParseErrs {
530 let errs: Vec<ParseErrs> = errs.into_iter().map(|e| e.into()).collect();
531
532 let source = if let Some(first) = errs.first() {
533 if let Some(source) = first.source.as_ref().cloned() {
534 Some(source)
535 } else {
536 None
537 }
538 } else {
539 None
540 };
541
542 let mut rtn = ParseErrs {
543 report: vec![],
544 source,
545 ctx: "".to_string(),
546 };
547
548 for err in errs {
549 for report in err.report {
550 rtn.report.push(report)
551 }
552 }
553 rtn
554 }
555}
556
557impl From<SpaceErr> for ParseErrs {
558 fn from(u: SpaceErr) -> Self {
559 ParseErrs {
560 report: vec![],
561 source: None,
562 ctx: "".to_string(),
563 }
564 }
565}
566
567impl From<serde_urlencoded::de::Error> for SpaceErr {
568 fn from(err: serde_urlencoded::de::Error) -> Self {
569 SpaceErr::Status {
570 status: 500u16,
571 message: err.to_string(),
572 }
573 }
574}
575
576impl From<serde_urlencoded::ser::Error> for SpaceErr {
577 fn from(err: serde_urlencoded::ser::Error) -> Self {
578 SpaceErr::Status {
579 status: 500u16,
580 message: err.to_string(),
581 }
582 }
583}
584
585pub mod report {
586 use serde::{Deserialize, Serialize};
587
588 #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
589 pub struct Report {
590 kind: ReportKind,
591 code: Option<String>,
592 msg: Option<String>,
593 note: Option<String>,
594 help: Option<String>,
595 location: Range,
596 labels: Vec<Label>,
597 }
598
599 impl Into<ariadne::Report> for Report {
600 fn into(self) -> ariadne::Report {
601 let mut builder = ariadne::Report::build(self.kind.into(), (), 0);
602 if let Some(msg) = self.msg {
603 builder.set_message(msg);
604 }
605 for label in self.labels {
606 builder.add_label(label.into());
607 }
608 builder.finish()
609 }
610 }
611
612 impl Default for Report {
613 fn default() -> Self {
614 Self {
615 kind: ReportKind::Error,
616 code: None,
617 msg: None,
618 note: None,
619 help: None,
620 location: Range { start: 0, end: 0 },
621 labels: vec![],
622 }
623 }
624 }
625
626 pub struct ReportBuilder {
627 kind: ReportKind,
628 code: Option<String>,
629 msg: Option<String>,
630 note: Option<String>,
631 help: Option<String>,
632 location: Range,
633 labels: Vec<Label>,
634 }
635
636 impl ReportBuilder {
637 pub fn with_message<S: ToString>(mut self, message: S) -> Self {
638 self.msg.replace(message.to_string());
639 self
640 }
641
642 pub fn with_label(mut self, label: Label) -> Self {
643 self.labels.push(label);
644 self
645 }
646
647 pub fn finish(self) -> Report {
648 Report {
649 kind: self.kind,
650 code: None,
651 msg: self.msg,
652 note: None,
653 help: None,
654 location: self.location,
655 labels: self.labels,
656 }
657 }
658 }
659
660 impl Report {
661 pub(crate) fn build(kind: ReportKind, p1: (), p2: i32) -> ReportBuilder {
662 ReportBuilder {
663 kind,
664 code: None,
665 msg: None,
666 note: None,
667 help: None,
668 location: Default::default(),
669 labels: vec![],
670 }
671 }
672 }
673
674 #[derive(Serialize, Deserialize, Copy, Clone, Debug, PartialEq, Eq)]
675 pub enum ReportKind {
676 Error,
677 Warning,
678 Advice,
679 }
680
681 impl Into<ariadne::ReportKind> for ReportKind {
682 fn into(self) -> ariadne::ReportKind {
683 match self {
684 ReportKind::Error => ariadne::ReportKind::Error,
685 ReportKind::Warning => ariadne::ReportKind::Warning,
686 ReportKind::Advice => ariadne::ReportKind::Advice,
687 }
688 }
689 }
690
691 #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
692 pub struct Range {
693 pub start: u32,
694 pub end: u32,
695 }
696
697 impl Into<std::ops::Range<usize>> for Range {
698 fn into(self) -> std::ops::Range<usize> {
699 std::ops::Range {
700 start: self.start as usize,
701 end: self.end as usize,
702 }
703 }
704 }
705
706 impl Default for Range {
707 fn default() -> Self {
708 Self { start: 0, end: 0 }
709 }
710 }
711
712 #[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
713 pub struct Label {
714 span: Range,
715 msg: Option<String>,
716 color: Option<Color>,
717 order: i32,
718 priority: i32,
719 }
720
721 impl Into<ariadne::Label> for Label {
722 fn into(self) -> ariadne::Label {
723 let mut rtn = ariadne::Label::new(self.span.into());
724 if let Some(msg) = self.msg {
725 rtn = rtn.with_message(msg);
726 }
727 rtn
728 }
729 }
730
731 impl Label {
732 pub fn new(range: std::ops::Range<usize>) -> Self {
733 Self {
734 span: Range {
735 start: range.start as u32,
736 end: range.end as u32,
737 },
738 msg: None,
739 color: None,
740 order: 0,
741 priority: 0,
742 }
743 }
744
745 pub fn with_message(mut self, msg: &str) -> Label {
746 self.msg.replace(msg.to_string());
747 self
748 }
749 }
750
751 #[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Copy, Clone)]
752 pub enum Color {
753 Unset,
755
756 Default,
758
759 Black,
761
762 Red,
764
765 Green,
767
768 Yellow,
770
771 Blue,
773
774 Magenta,
776
777 Cyan,
779
780 White,
782
783 Fixed(u8),
785
786 RGB(u8, u8, u8),
788 }
789}
790
791#[cfg(test)]
792pub mod test {
793
794 #[test]
795 pub fn compile() {}
796}