cosmic_space/
err.rs

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
114/*
115impl Into<ParseErrs> for UniErr {
116    fn into(self) -> ParseErrs {
117        match self {
118            UniErr::Status { status, message } => {
119                let mut builder = Report::build(ReportKind::Error, (), 0);
120                let report = builder.with_message(message).finish();
121                let errs = ParseErrs {
122                    report: vec![report],
123                    source: None,
124                };
125                errs
126            }
127            UniErr::ParseErrs(errs) => errs,
128        }
129    }
130}
131
132 */
133
134impl 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
378/*
379impl From<ToStrError> for UniErr {
380    fn from(x: ToStrError) -> Self {
381        Self::Status {
382            status: 500,
383            message: x.to_string(),
384        }
385    }
386}
387
388 */
389
390impl<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        /// No color has been set. Nothing is changed when applied.
754        Unset,
755
756        /// Terminal default #9. (foreground code `39`, background code `49`).
757        Default,
758
759        /// Black #0 (foreground code `30`, background code `40`).
760        Black,
761
762        /// Red: #1 (foreground code `31`, background code `41`).
763        Red,
764
765        /// Green: #2 (foreground code `32`, background code `42`).
766        Green,
767
768        /// Yellow: #3 (foreground code `33`, background code `43`).
769        Yellow,
770
771        /// Blue: #4 (foreground code `34`, background code `44`).
772        Blue,
773
774        /// Magenta: #5 (foreground code `35`, background code `45`).
775        Magenta,
776
777        /// Cyan: #6 (foreground code `36`, background code `46`).
778        Cyan,
779
780        /// White: #7 (foreground code `37`, background code `47`).
781        White,
782
783        /// A color number from 0 to 255, for use in 256-color terminals.
784        Fixed(u8),
785
786        /// A 24-bit RGB color, as specified by ISO-8613-3.
787        RGB(u8, u8, u8),
788    }
789}
790
791#[cfg(test)]
792pub mod test {
793
794    #[test]
795    pub fn compile() {}
796}