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
|
// Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use super::{ATTRIBUTE_NAME, END_VERSION, START_VERSION};
use common::Exists;
use quote::format_ident;
use std::cmp::max;
use std::collections::hash_map::HashMap;
// Returns a string literal attribute as an Ident.
pub(crate) fn get_ident_attr(
attrs: &HashMap<String, syn::Lit>,
attr_name: &str,
) -> Option<syn::Ident> {
attrs.get(attr_name).map(|default_fn| match default_fn {
syn::Lit::Str(lit_str) => {
format_ident!("{}", lit_str.value())
}
_ => panic!("default_fn must be the function name as a String."),
})
}
pub(crate) fn get_start_version(attrs: &HashMap<String, syn::Lit>) -> Option<u16> {
if let Some(start_version) = attrs.get(START_VERSION) {
return Some(match start_version {
syn::Lit::Int(lit_int) => lit_int.base10_parse().unwrap(),
_ => panic!("Field start/end version number must be an integer"),
});
}
None
}
pub(crate) fn get_end_version(attrs: &HashMap<String, syn::Lit>) -> Option<u16> {
if let Some(start_version) = attrs.get(END_VERSION) {
return Some(match start_version {
syn::Lit::Int(lit_int) => lit_int.base10_parse().unwrap(),
_ => panic!("Field start/end version number must be an integer"),
});
}
None
}
// Returns an attribute hash_map constructed by processing a vector of syn::Attribute.
pub(crate) fn parse_field_attributes(attributes: &[syn::Attribute]) -> HashMap<String, syn::Lit> {
let mut attrs = HashMap::new();
for nested_attr in attributes
.iter()
.flat_map(|attr| -> Result<Vec<syn::NestedMeta>, ()> {
if !attr.path.is_ident(ATTRIBUTE_NAME) {
return Ok(Vec::new());
}
if let Ok(syn::Meta::List(meta)) = attr.parse_meta() {
return Ok(meta.nested.into_iter().collect());
}
Ok(Vec::new())
})
.flatten()
{
if let syn::NestedMeta::Meta(syn::Meta::NameValue(attr_name_value)) = nested_attr {
attrs.insert(
attr_name_value.path.get_ident().unwrap().to_string(),
attr_name_value.lit,
);
}
}
attrs
}
// Compute current struct version by finding the latest field change version.
pub(crate) fn compute_version<T>(fields: &[T]) -> u16
where
T: Exists,
{
let mut version = 0;
for field in fields {
version = max(version, max(field.start_version(), field.end_version()));
}
version
}
|