1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
use proc_macro2::Span;
use proc_macro_crate::{crate_name, FoundCrate};
use proc_macro_error::ResultExt;
use quote::format_ident;
use std::convert::*;
use super::field_type::*;
pub fn as_holder_visitor(input: &syn::Ident) -> syn::Ident {
format_ident!("{}HolderVisitor", input)
}
pub fn as_holder_ident(input: &syn::Ident) -> syn::Ident {
format_ident!("{}Holder", input)
}
pub fn as_holder_path(input: &syn::Type) -> syn::Type {
let ft: FieldType = input
.clone()
.try_into()
.expect_or_abort("as_holder! only accepts espr-generated type");
ft.as_holder().into()
}
pub fn as_visitor_ident(input: &syn::Ident) -> syn::Ident {
format_ident!("{}Visitor", input)
}
pub fn serde_crate() -> syn::Path {
let ruststep = ruststep_crate();
syn::parse_quote!( #ruststep::serde )
}
pub fn itertools_crate() -> syn::Path {
let ruststep = ruststep_crate();
syn::parse_quote!( #ruststep::itertools )
}
pub fn ruststep_crate() -> syn::Path {
let path = crate_name("ruststep").unwrap();
match path {
FoundCrate::Itself => match std::env::var("CARGO_TARGET_TMPDIR") {
Ok(_) => {
let mut segments = syn::punctuated::Punctuated::new();
segments.push(syn::PathSegment {
ident: syn::Ident::new("ruststep", Span::call_site()),
arguments: syn::PathArguments::None,
});
syn::Path {
leading_colon: Some(syn::token::PathSep::default()),
segments,
}
}
Err(_) => {
let mut segments = syn::punctuated::Punctuated::new();
segments.push(syn::PathSegment {
ident: syn::Ident::new("crate", Span::call_site()),
arguments: syn::PathArguments::None,
});
syn::Path {
leading_colon: None,
segments,
}
}
},
FoundCrate::Name(name) => {
let mut segments = syn::punctuated::Punctuated::new();
segments.push(syn::PathSegment {
ident: syn::Ident::new(&name, Span::call_site()),
arguments: syn::PathArguments::None,
});
syn::Path {
leading_colon: Some(syn::token::PathSep::default()),
segments,
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn holder_path() {
let path = syn::parse_str("::some::Struct").unwrap();
let holder = as_holder_path(&path);
let ans = syn::parse_str("::some::StructHolder").unwrap();
assert_eq!(holder, ans);
}
#[test]
fn optional_holder_path() {
let path = syn::parse_str("Option<::some::Struct>").unwrap();
let holder = as_holder_path(&path);
let ans = syn::parse_str("Option<::some::StructHolder>").unwrap();
assert_eq!(holder, ans);
}
}