serde_json_path_macros_internal-0.1.2/.cargo_vcs_info.json0000644000000002010000000000100174340ustar { "git": { "sha1": "273904f4de1d2759e82e0c15ed2f529c5f6c21b6" }, "path_in_vcs": "serde_json_path_macros/src/internal" }serde_json_path_macros_internal-0.1.2/Cargo.toml0000644000000022450000000000100154440ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" name = "serde_json_path_macros_internal" version = "0.1.2" authors = ["Trevor Hilton "] build = false autobins = false autoexamples = false autotests = false autobenches = false description = "Internal macro implementation for the serde_json_path crate" readme = "README.md" keywords = [ "json", "jsonpath", "json_path", "serde", "serde_json", ] license = "MIT" repository = "https://github.com/hiltontj/serde_json_path" [lib] name = "serde_json_path_macros_internal" path = "mod.rs" proc-macro = true [dependencies.proc-macro2] version = "1.0.89" [dependencies.quote] version = "1.0.37" [dependencies.syn] version = "2.0.87" features = ["full"] serde_json_path_macros_internal-0.1.2/Cargo.toml.orig000064400000000000000000000010171046102023000211210ustar 00000000000000[package] name = "serde_json_path_macros_internal" version = "0.1.2" edition = "2021" license = "MIT" authors = ["Trevor Hilton "] description = "Internal macro implementation for the serde_json_path crate" repository = "https://github.com/hiltontj/serde_json_path" readme = "README.md" keywords = ["json", "jsonpath", "json_path", "serde", "serde_json"] [lib] proc-macro = true path = "mod.rs" [dependencies] proc-macro2 = "1.0.89" quote = "1.0.37" syn = { version = "2.0.87", features = ["full"] } serde_json_path_macros_internal-0.1.2/LICENSE-MIT000064400000000000000000000020561046102023000176720ustar 00000000000000MIT License Copyright (c) 2023 Trevor Hilton Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. serde_json_path_macros_internal-0.1.2/README.md000064400000000000000000000002311046102023000175060ustar 00000000000000# serde_json_path_macros_internal This is an internal crate used by the [`serde_json_path`][sjp] crate. [sjp]: https://crates.io/crates/serde_json_pathserde_json_path_macros_internal-0.1.2/common/args.rs000064400000000000000000000016251046102023000210310ustar 00000000000000use proc_macro2::Ident; use syn::{ parse::{Parse, ParseStream}, LitStr, Token, }; pub(crate) struct StrArg { pub(crate) value: LitStr, _p: std::marker::PhantomData, } impl Parse for StrArg { fn parse(input: ParseStream<'_>) -> syn::Result { let _ = input.parse::()?; let _ = input.parse::()?; let value = input.parse()?; Ok(Self { value, _p: std::marker::PhantomData, }) } } pub(crate) struct IdentArg { pub(crate) value: Ident, _p: std::marker::PhantomData, } impl Parse for IdentArg { fn parse(input: ParseStream) -> syn::Result { let _ = input.parse::()?; let _ = input.parse::()?; let value = input.parse()?; Ok(Self { value, _p: std::marker::PhantomData, }) } } serde_json_path_macros_internal-0.1.2/common/define.rs000064400000000000000000000077751046102023000213430ustar 00000000000000use proc_macro2::{Ident, TokenStream}; use quote::quote; use syn::{ItemFn, LitStr}; use crate::common::extract::FnArgument; use super::extract::{extract_components, Components}; pub(crate) struct Expanded { pub(crate) name_str: LitStr, pub(crate) validator: TokenStream, pub(crate) validator_name: Ident, pub(crate) evaluator: TokenStream, pub(crate) evaluator_name: Ident, pub(crate) result: TokenStream, pub(crate) core: TokenStream, } /// Expand the macro input to produce the common elements used in the `#[function]` and /// `#[register]` macros. pub(crate) fn expand(input: ItemFn, name_str: Option) -> Result { let ItemFn { attrs: _, vis: _, sig, block, } = input; let Components { name, generics, validator_name, evaluator_name, result, args, ret, inputs, } = match extract_components(sig) { Ok(fd) => fd, Err(e) => return Err(e.into_compile_error()), }; // Stringified name of the function: let name_str = name_str.unwrap_or_else(|| LitStr::new(name.to_string().as_str(), name.span())); // The number of arguments the function accepts: let args_len = args.len(); // Generate token streams for some needed types: let lazy = quote! { std::sync::LazyLock }; let core = quote! { ::serde_json_path_macros::serde_json_path_core::spec::functions }; let res = quote! { std::result::Result }; // Generate code for checking each individual argument in a query at parse time: let arg_checks = args.iter().enumerate().map(|(idx, arg)| { let FnArgument { ident: _, ty } = arg; quote! { match a[#idx].as_type_kind() { #res::Ok(tk) => { if !tk.converts_to(#ty::json_path_type()) { return #res::Err(#core::FunctionValidationError::MismatchTypeKind { name: String::from(#name_str), expected: #ty::json_path_type(), received: tk, position: #idx, }); } }, #res::Err(err) => return #res::Err(err) } } }); // Generate the validator function used at parse time to validate a function declaration: let validator = quote! { static #validator_name: #core::Validator = #lazy::new(|| { std::boxed::Box::new(|a: &[#core::FunctionExprArg]| { if a.len() != #args_len { return #res::Err(#core::FunctionValidationError::NumberOfArgsMismatch { expected: a.len(), received: #args_len, }); } #(#arg_checks)* Ok(()) }) }); }; // Generate the code to declare each individual argument for evaluation, at query time: let arg_declarations = args.iter().map(|arg| { let FnArgument { ident, ty } = arg; // validation should ensure unwrap is okay here: quote! { let #ident = #ty::try_from(v.pop_front().unwrap()).unwrap(); } }); // Produce the argument name identifiers: let arg_names = args.iter().map(|arg| { let FnArgument { ident, ty: _ } = arg; ident }); // Generate the evaluator function used to evaluate a function at query time: let evaluator = quote! { fn #name #generics (#inputs) #ret #block static #evaluator_name: #core::Evaluator = #lazy::new(|| { std::boxed::Box::new(|mut v: std::collections::VecDeque<#core::JsonPathValue>| { #(#arg_declarations)* return #name(#(#arg_names,)*).into() }) }); }; Ok(Expanded { name_str, validator, validator_name, evaluator, evaluator_name, result, core, }) } serde_json_path_macros_internal-0.1.2/common/extract.rs000064400000000000000000000110371046102023000215450ustar 00000000000000use std::collections::VecDeque; use proc_macro2::{Ident, TokenStream}; use quote::quote; use syn::{ punctuated::Punctuated, spanned::Spanned, token::Comma, Error, FnArg, Generics, Pat, PatType, Path, Result, ReturnType, Signature, Type, }; pub struct Components { pub name: Ident, pub generics: Generics, pub validator_name: Ident, pub evaluator_name: Ident, pub result: TokenStream, pub ret: ReturnType, pub inputs: Punctuated, pub args: VecDeque, } pub struct FnArgument { pub ident: Ident, pub ty: TokenStream, } fn extract_pat_ident(pat: &Pat) -> Option { if let Pat::Ident(ref pat_ident) = pat { Some(pat_ident.ident.to_owned()) } else { None } } fn extract_type_path(ty: &Type) -> Option<&Path> { match ty { Type::Path(ref typepath) if typepath.qself.is_none() => Some(&typepath.path), Type::Reference(ref typeref) => match *typeref.elem { Type::Path(ref typepath) if typepath.qself.is_none() => Some(&typepath.path), _ => None, }, _ => None, } } fn extract_json_path_type(p: &Path) -> Result { let p_seg = p .segments .last() .ok_or_else(|| Error::new(p.span(), "expected a type identifier"))?; let ts = match p_seg.ident.to_string().as_str() { "NodesType" => quote! { ::serde_json_path_macros::serde_json_path_core::spec::functions::NodesType }, "ValueType" => quote! { ::serde_json_path_macros::serde_json_path_core::spec::functions::ValueType }, "LogicalType" => quote! { ::serde_json_path_macros::serde_json_path_core::spec::functions::LogicalType }, other => { return Err(Error::new( p_seg.ident.span(), format!( "expected 'NodesType', 'ValueType', or 'LogicalType', got '{}'", other, ), )) } }; Ok(ts) } pub fn extract_components(input: Signature) -> Result { let name = input.ident.clone(); let generics = input.generics.clone(); let inputs = input.inputs.clone(); let ret = input.output.clone(); let result = match &ret { ReturnType::Default => { return Err(Error::new( input.span(), "function signature expected to have return type", )) } ReturnType::Type(_, ty) => { if let Some(path) = extract_type_path(ty.as_ref()) { extract_json_path_type(path)? } else { return Err(Error::new( ty.span(), "return type can only be one of the serde_json_path types: NodesType, \ ValueType, or LogicalType", )); } } }; let args: Result> = inputs .iter() .map(|i| match i { FnArg::Receiver(_) => Err(Error::new( inputs.span(), "receiver arguments like self, &self, or &mut self are not supported", )), FnArg::Typed(PatType { attrs: _, pat, colon_token: _, ty, }) => { let ident = if let Some(id) = extract_pat_ident(pat) { id } else { return Err(Error::new( pat.span(), "expected identifier in function argument", )); }; let ty = if let Some(path) = extract_type_path(ty) { extract_json_path_type(path)? } else { return Err(Error::new( ty.span(), "argument type can only be one of the serde_json_path types: NodesType, \ ValueType, or LogicalType", )); }; Ok(FnArgument { ident, ty }) } }) .collect(); let args = args?; let validator_name = Ident::new( format!("{name}_validator").to_uppercase().as_str(), name.span(), ); let evaluator_name = Ident::new( format!("{name}_evaluator").to_uppercase().as_str(), name.span(), ); Ok(Components { name, generics, result, inputs, ret, args, validator_name, evaluator_name, }) } serde_json_path_macros_internal-0.1.2/common/mod.rs000064400000000000000000000001041046102023000206430ustar 00000000000000pub(crate) mod args; pub(crate) mod define; pub(crate) mod extract; serde_json_path_macros_internal-0.1.2/func/args.rs000064400000000000000000000020771046102023000204760ustar 00000000000000use syn::{parse::Parse, LitStr}; use crate::common::args::StrArg; #[derive(Default)] pub(crate) struct FunctionMacroArgs { pub(crate) name: Option, } impl Parse for FunctionMacroArgs { fn parse(input: syn::parse::ParseStream) -> syn::Result { let mut args = Self::default(); while !input.is_empty() { let lookahead = input.lookahead1(); if lookahead.peek(kw::name) { if args.name.is_some() { return Err(input.error("expected only a single `name` argument")); } let name = input.parse::>()?.value; args.name = Some(name); } else { // TODO - may want to warn here when found a invalid arg - see how // tracing::instrument stores warnings and emits them later when generating the // expanded token stream. let _ = input.parse::(); } } Ok(args) } } mod kw { syn::custom_keyword!(name); } serde_json_path_macros_internal-0.1.2/func/define.rs000064400000000000000000000015751046102023000207760ustar 00000000000000use proc_macro::TokenStream; use quote::quote; use syn::ItemFn; use crate::common::{self, define::Expanded}; use super::args::FunctionMacroArgs; pub(crate) fn expand(attrs: FunctionMacroArgs, input: ItemFn) -> TokenStream { let Expanded { name_str, validator, validator_name, evaluator, evaluator_name, result, core, } = match common::define::expand(input, attrs.name) { Ok(exp) => exp, Err(err) => return err.into(), }; let inventory = quote! { ::serde_json_path_macros::inventory }; TokenStream::from(quote! { #validator #evaluator #inventory::submit! { #core::Function::new( #name_str, #result::function_type(), &#evaluator_name, &#validator_name, ) } }) } serde_json_path_macros_internal-0.1.2/func/mod.rs000064400000000000000000000001361046102023000203130ustar 00000000000000mod args; mod define; pub(crate) use args::FunctionMacroArgs; pub(crate) use define::expand; serde_json_path_macros_internal-0.1.2/mod.rs000064400000000000000000000011331046102023000173560ustar 00000000000000use proc_macro::TokenStream; use syn::{parse_macro_input, ItemFn}; mod common; mod func; mod reg; #[proc_macro_attribute] pub fn function(attr: TokenStream, item: TokenStream) -> TokenStream { let args = parse_macro_input!(attr as func::FunctionMacroArgs); let item_fn = parse_macro_input!(item as ItemFn); func::expand(args, item_fn) } #[proc_macro_attribute] pub fn register(attr: TokenStream, item: TokenStream) -> TokenStream { let args = parse_macro_input!(attr as reg::RegisterMacroArgs); let item_fn = parse_macro_input!(item as ItemFn); reg::expand(args, item_fn) } serde_json_path_macros_internal-0.1.2/reg/args.rs000064400000000000000000000033751046102023000203220ustar 00000000000000use proc_macro2::Ident; use syn::{parse::Parse, LitStr}; use crate::common::args::{IdentArg, StrArg}; pub(crate) struct RegisterMacroArgs { pub(crate) name: Option, pub(crate) target: Ident, } #[derive(Default)] struct RegisterMacroArgsBuilder { name: Option, target: Option, } impl RegisterMacroArgsBuilder { fn build(self, input: &syn::parse::ParseStream) -> syn::Result { if let Some(target) = self.target { Ok(RegisterMacroArgs { name: self.name, target, }) } else { Err(input.error("missing `target` argument")) } } } impl Parse for RegisterMacroArgs { fn parse(input: syn::parse::ParseStream) -> syn::Result { let mut builder = RegisterMacroArgsBuilder::default(); while !input.is_empty() { let lookahead = input.lookahead1(); if lookahead.peek(kw::name) { if builder.name.is_some() { return Err(input.error("expected only a single `name` argument")); } let name = input.parse::>()?.value; builder.name = Some(name); } else if lookahead.peek(kw::target) { if builder.target.is_some() { return Err(input.error("expected only a single `target` argument")); } let target = input.parse::>()?.value; builder.target = Some(target); } else { let _ = input.parse::(); } } builder.build(&input) } } mod kw { syn::custom_keyword!(name); syn::custom_keyword!(target); } serde_json_path_macros_internal-0.1.2/reg/define.rs000064400000000000000000000014761046102023000206200ustar 00000000000000use proc_macro::TokenStream; use quote::quote; use syn::ItemFn; use crate::common::{self, define::Expanded}; use super::args::RegisterMacroArgs; pub(crate) fn expand(attrs: RegisterMacroArgs, input: ItemFn) -> TokenStream { let RegisterMacroArgs { name, target } = attrs; let Expanded { name_str, validator, validator_name, evaluator, evaluator_name, result, core, } = match common::define::expand(input, name) { Ok(exp) => exp, Err(err) => return err.into(), }; TokenStream::from(quote! { #validator #evaluator static #target: #core::Function = #core::Function::new( #name_str, #result::function_type(), &#evaluator_name, &#validator_name, ); }) } serde_json_path_macros_internal-0.1.2/reg/mod.rs000064400000000000000000000001361046102023000201350ustar 00000000000000mod args; mod define; pub(crate) use args::RegisterMacroArgs; pub(crate) use define::expand;