summaryrefslogtreecommitdiffstats
path: root/third_party/rust/serde_derive/src/fragment.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/serde_derive/src/fragment.rs')
-rw-r--r--third_party/rust/serde_derive/src/fragment.rs74
1 files changed, 74 insertions, 0 deletions
diff --git a/third_party/rust/serde_derive/src/fragment.rs b/third_party/rust/serde_derive/src/fragment.rs
new file mode 100644
index 0000000000..6627c26699
--- /dev/null
+++ b/third_party/rust/serde_derive/src/fragment.rs
@@ -0,0 +1,74 @@
+use proc_macro2::TokenStream;
+use quote::ToTokens;
+use syn::{token, Token};
+
+pub enum Fragment {
+ /// Tokens that can be used as an expression.
+ Expr(TokenStream),
+ /// Tokens that can be used inside a block. The surrounding curly braces are
+ /// not part of these tokens.
+ Block(TokenStream),
+}
+
+macro_rules! quote_expr {
+ ($($tt:tt)*) => {
+ $crate::fragment::Fragment::Expr(quote!($($tt)*))
+ }
+}
+
+macro_rules! quote_block {
+ ($($tt:tt)*) => {
+ $crate::fragment::Fragment::Block(quote!($($tt)*))
+ }
+}
+
+/// Interpolate a fragment in place of an expression. This involves surrounding
+/// Block fragments in curly braces.
+pub struct Expr(pub Fragment);
+impl ToTokens for Expr {
+ fn to_tokens(&self, out: &mut TokenStream) {
+ match &self.0 {
+ Fragment::Expr(expr) => expr.to_tokens(out),
+ Fragment::Block(block) => {
+ token::Brace::default().surround(out, |out| block.to_tokens(out));
+ }
+ }
+ }
+}
+
+/// Interpolate a fragment as the statements of a block.
+pub struct Stmts(pub Fragment);
+impl ToTokens for Stmts {
+ fn to_tokens(&self, out: &mut TokenStream) {
+ match &self.0 {
+ Fragment::Expr(expr) => expr.to_tokens(out),
+ Fragment::Block(block) => block.to_tokens(out),
+ }
+ }
+}
+
+/// Interpolate a fragment as the value part of a `match` expression. This
+/// involves putting a comma after expressions and curly braces around blocks.
+pub struct Match(pub Fragment);
+impl ToTokens for Match {
+ fn to_tokens(&self, out: &mut TokenStream) {
+ match &self.0 {
+ Fragment::Expr(expr) => {
+ expr.to_tokens(out);
+ <Token![,]>::default().to_tokens(out);
+ }
+ Fragment::Block(block) => {
+ token::Brace::default().surround(out, |out| block.to_tokens(out));
+ }
+ }
+ }
+}
+
+impl AsRef<TokenStream> for Fragment {
+ fn as_ref(&self) -> &TokenStream {
+ match self {
+ Fragment::Expr(expr) => expr,
+ Fragment::Block(block) => block,
+ }
+ }
+}