summaryrefslogtreecommitdiffstats
path: root/third_party/rust/time-macros/src/error.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/time-macros/src/error.rs')
-rw-r--r--third_party/rust/time-macros/src/error.rs123
1 files changed, 123 insertions, 0 deletions
diff --git a/third_party/rust/time-macros/src/error.rs b/third_party/rust/time-macros/src/error.rs
new file mode 100644
index 0000000000..849317f15f
--- /dev/null
+++ b/third_party/rust/time-macros/src/error.rs
@@ -0,0 +1,123 @@
+use std::borrow::Cow;
+use std::fmt;
+
+use proc_macro::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
+
+trait WithSpan {
+ fn with_span(self, span: Span) -> Self;
+}
+
+impl WithSpan for TokenTree {
+ fn with_span(mut self, span: Span) -> Self {
+ self.set_span(span);
+ self
+ }
+}
+
+pub(crate) enum Error {
+ MissingComponent {
+ name: &'static str,
+ span_start: Option<Span>,
+ span_end: Option<Span>,
+ },
+ InvalidComponent {
+ name: &'static str,
+ value: String,
+ span_start: Option<Span>,
+ span_end: Option<Span>,
+ },
+ #[cfg(any(feature = "formatting", feature = "parsing"))]
+ ExpectedString {
+ span_start: Option<Span>,
+ span_end: Option<Span>,
+ },
+ UnexpectedToken {
+ tree: TokenTree,
+ },
+ UnexpectedEndOfInput,
+ Custom {
+ message: Cow<'static, str>,
+ span_start: Option<Span>,
+ span_end: Option<Span>,
+ },
+}
+
+impl fmt::Display for Error {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ Self::MissingComponent { name, .. } => write!(f, "missing component: {name}"),
+ Self::InvalidComponent { name, value, .. } => {
+ write!(f, "invalid component: {name} was {value}")
+ }
+ #[cfg(any(feature = "formatting", feature = "parsing"))]
+ Self::ExpectedString { .. } => f.write_str("expected string literal"),
+ Self::UnexpectedToken { tree } => write!(f, "unexpected token: {tree}"),
+ Self::UnexpectedEndOfInput => f.write_str("unexpected end of input"),
+ Self::Custom { message, .. } => f.write_str(message),
+ }
+ }
+}
+
+impl Error {
+ fn span_start(&self) -> Span {
+ match self {
+ Self::MissingComponent { span_start, .. }
+ | Self::InvalidComponent { span_start, .. }
+ | Self::Custom { span_start, .. } => *span_start,
+ #[cfg(any(feature = "formatting", feature = "parsing"))]
+ Self::ExpectedString { span_start, .. } => *span_start,
+ Self::UnexpectedToken { tree } => Some(tree.span()),
+ Self::UnexpectedEndOfInput => Some(Span::mixed_site()),
+ }
+ .unwrap_or_else(Span::mixed_site)
+ }
+
+ fn span_end(&self) -> Span {
+ match self {
+ Self::MissingComponent { span_end, .. }
+ | Self::InvalidComponent { span_end, .. }
+ | Self::Custom { span_end, .. } => *span_end,
+ #[cfg(any(feature = "formatting", feature = "parsing"))]
+ Self::ExpectedString { span_end, .. } => *span_end,
+ Self::UnexpectedToken { tree, .. } => Some(tree.span()),
+ Self::UnexpectedEndOfInput => Some(Span::mixed_site()),
+ }
+ .unwrap_or_else(|| self.span_start())
+ }
+
+ pub(crate) fn to_compile_error(&self) -> TokenStream {
+ let (start, end) = (self.span_start(), self.span_end());
+
+ [
+ TokenTree::from(Punct::new(':', Spacing::Joint)).with_span(start),
+ TokenTree::from(Punct::new(':', Spacing::Alone)).with_span(start),
+ TokenTree::from(Ident::new("core", start)),
+ TokenTree::from(Punct::new(':', Spacing::Joint)).with_span(start),
+ TokenTree::from(Punct::new(':', Spacing::Alone)).with_span(start),
+ TokenTree::from(Ident::new("compile_error", start)),
+ TokenTree::from(Punct::new('!', Spacing::Alone)).with_span(start),
+ TokenTree::from(Group::new(
+ Delimiter::Parenthesis,
+ TokenStream::from(
+ TokenTree::from(Literal::string(&self.to_string())).with_span(end),
+ ),
+ ))
+ .with_span(end),
+ ]
+ .iter()
+ .cloned()
+ .collect()
+ }
+
+ /// Like `to_compile_error`, but for use in macros that produce items.
+ #[cfg(all(feature = "serde", any(feature = "formatting", feature = "parsing")))]
+ pub(crate) fn to_compile_error_standalone(&self) -> TokenStream {
+ let end = self.span_end();
+ self.to_compile_error()
+ .into_iter()
+ .chain(std::iter::once(
+ TokenTree::from(Punct::new(';', Spacing::Alone)).with_span(end),
+ ))
+ .collect()
+ }
+}