Download proc-macros/src/helper_structs.rs from openfree/graphite2: direct link, hf CLI and curl.
- Browser
- Download file 4.55 kB
-
https://huggingface.co/spaces/openfree/graphite2/resolve/main/proc-macros/src/helper_structs.rs
- Command line
-
hf download hf://spaces/openfree/graphite2/proc-macros/src/helper_structs.rs
-
curl -L -o helper_structs.rs https://huggingface.co/spaces/openfree/graphite2/resolve/main/proc-macros/src/helper_structs.rs
4.55 kB
| use proc_macro2::{Ident, TokenStream}; | |
| use std::collections::HashMap; | |
| use syn::parse::{Parse, ParseStream}; | |
| use syn::punctuated::Punctuated; | |
| use syn::token::Paren; | |
| use syn::{LitStr, Token, parenthesized}; | |
| pub struct IdentList { | |
| pub parts: Punctuated<Ident, Token![,]>, | |
| } | |
| impl Parse for IdentList { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| let content; | |
| let _paren_token = parenthesized!(content in input); | |
| Ok(Self { | |
| parts: Punctuated::parse_terminated(&content)?, | |
| }) | |
| } | |
| } | |
| /// Parses `("some text")` | |
| pub struct AttrInnerSingleString { | |
| _paren_token: Paren, | |
| pub content: LitStr, | |
| } | |
| impl Parse for AttrInnerSingleString { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| let content; | |
| let _paren_token = parenthesized!(content in input); | |
| Ok(Self { | |
| _paren_token, | |
| content: content.parse()?, | |
| }) | |
| } | |
| } | |
| /// Parses `key="value"` | |
| pub struct KeyEqString { | |
| key: Ident, | |
| _eq_token: Token![=], | |
| lit: LitStr, | |
| } | |
| impl Parse for KeyEqString { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| Ok(Self { | |
| key: input.parse()?, | |
| _eq_token: input.parse()?, | |
| lit: input.parse()?, | |
| }) | |
| } | |
| } | |
| /// Parses `(key="value", key="value", …)` | |
| pub struct AttrInnerKeyStringMap { | |
| parts: Punctuated<KeyEqString, Token![,]>, | |
| } | |
| impl Parse for AttrInnerKeyStringMap { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| Ok(Self { | |
| parts: Punctuated::parse_terminated(input)?, | |
| }) | |
| } | |
| } | |
| impl AttrInnerKeyStringMap { | |
| pub fn multi_into_iter(iter: impl IntoIterator<Item = Self>) -> impl Iterator<Item = (Ident, Vec<LitStr>)> { | |
| use std::collections::hash_map::Entry; | |
| let mut res = Vec::<(Ident, Vec<LitStr>)>::new(); | |
| let mut idx = HashMap::<Ident, usize>::new(); | |
| for part in iter.into_iter().flat_map(|x: Self| x.parts) { | |
| match idx.entry(part.key) { | |
| Entry::Occupied(occ) => { | |
| res[*occ.get()].1.push(part.lit); | |
| } | |
| Entry::Vacant(vac) => { | |
| let ident = vac.key().clone(); | |
| vac.insert(res.len()); | |
| res.push((ident, vec![part.lit])); | |
| } | |
| } | |
| } | |
| res.into_iter() | |
| } | |
| } | |
| /// Parses `(left, right)` | |
| pub struct Pair<F, S> { | |
| pub first: F, | |
| pub sep: Token![,], | |
| pub second: S, | |
| } | |
| impl<F, S> Parse for Pair<F, S> | |
| where | |
| F: Parse, | |
| S: Parse, | |
| { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| Ok(Self { | |
| first: input.parse()?, | |
| sep: input.parse()?, | |
| second: input.parse()?, | |
| }) | |
| } | |
| } | |
| /// parses `(...)` | |
| pub struct ParenthesizedTokens { | |
| pub paren: Paren, | |
| pub tokens: TokenStream, | |
| } | |
| impl Parse for ParenthesizedTokens { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| let content; | |
| let paren = parenthesized!(content in input); | |
| Ok(Self { paren, tokens: content.parse()? }) | |
| } | |
| } | |
| /// parses a comma-delimeted list of `T`s with optional trailing comma | |
| pub struct SimpleCommaDelimeted<T>(pub Vec<T>); | |
| impl<T: Parse> Parse for SimpleCommaDelimeted<T> { | |
| fn parse(input: ParseStream) -> syn::Result<Self> { | |
| let punctuated = Punctuated::<T, Token![,]>::parse_terminated(input)?; | |
| Ok(Self(punctuated.into_iter().collect())) | |
| } | |
| } | |
| mod tests { | |
| use super::*; | |
| fn attr_inner_single_string() { | |
| let res = syn::parse2::<AttrInnerSingleString>(quote::quote! { | |
| ("a string literal") | |
| }); | |
| assert!(res.is_ok()); | |
| assert_eq!(res.ok().unwrap().content.value(), "a string literal"); | |
| let res = syn::parse2::<AttrInnerSingleString>(quote::quote! { | |
| wrong, "stuff" | |
| }); | |
| assert!(res.is_err()); | |
| } | |
| fn key_eq_string() { | |
| let res = syn::parse2::<KeyEqString>(quote::quote! { | |
| key="value" | |
| }); | |
| assert!(res.is_ok()); | |
| let res = res.ok().unwrap(); | |
| assert_eq!(res.key, "key"); | |
| assert_eq!(res.lit.value(), "value"); | |
| let res = syn::parse2::<KeyEqString>(quote::quote! { | |
| wrong, "stuff" | |
| }); | |
| assert!(res.is_err()); | |
| } | |
| fn attr_inner_key_string_map() { | |
| let res = syn::parse2::<AttrInnerKeyStringMap>(quote::quote! { | |
| key="value", key2="value2" | |
| }); | |
| assert!(res.is_ok()); | |
| let res = res.ok().unwrap(); | |
| for (item, (k, v)) in res.parts.into_iter().zip(vec![("key", "value"), ("key2", "value2")]) { | |
| assert_eq!(item.key, k); | |
| assert_eq!(item.lit.value(), v); | |
| } | |
| let res = syn::parse2::<AttrInnerKeyStringMap>(quote::quote! { | |
| key="value", key2="value2", | |
| }); | |
| assert!(res.is_ok()); | |
| let res = res.ok().unwrap(); | |
| for (item, (k, v)) in res.parts.into_iter().zip(vec![("key", "value"), ("key2", "value2")]) { | |
| assert_eq!(item.key, k); | |
| assert_eq!(item.lit.value(), v); | |
| } | |
| let res = syn::parse2::<AttrInnerKeyStringMap>(quote::quote! { | |
| wrong, "stuff" | |
| }); | |
| assert!(res.is_err()); | |
| } | |
| } | |