aranya_capi_codegen/
attr.rs

1//! Attribute support.
2
3use std::{fmt, iter::Iterator};
4
5use proc_macro2::TokenStream;
6use quote::ToTokens;
7use syn::{spanned::Spanned, Error, Ident, Path};
8
9/// An attribute name,
10#[derive(Copy, Clone)]
11pub struct Symbol(pub &'static str);
12
13impl PartialEq<Symbol> for Ident {
14    fn eq(&self, word: &Symbol) -> bool {
15        self == word.0
16    }
17}
18
19impl<'a> PartialEq<Symbol> for &'a Ident {
20    fn eq(&self, word: &Symbol) -> bool {
21        *self == word.0
22    }
23}
24
25impl PartialEq<Symbol> for Path {
26    fn eq(&self, word: &Symbol) -> bool {
27        PartialEq::eq(&self, word)
28    }
29}
30
31impl<'a> PartialEq<Symbol> for &'a Path {
32    fn eq(&self, word: &Symbol) -> bool {
33        Iterator::eq(
34            self.segments.iter().map(|seg| &seg.ident),
35            word.0.split("::"),
36        )
37    }
38}
39
40impl fmt::Display for Symbol {
41    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
42        write!(f, "{}", self.0)
43    }
44}
45
46/// An attribute.
47pub struct Attr<T> {
48    name: Symbol,
49    tokens: TokenStream,
50    value: Option<T>,
51}
52
53impl<T> Attr<T> {
54    /// Creates a new, unset attribute.
55    pub fn none(name: Symbol) -> Self {
56        Self {
57            name,
58            tokens: TokenStream::new(),
59            value: None,
60        }
61    }
62
63    /// Sets the attribute's value.
64    pub fn set<A: ToTokens>(&mut self, obj: A, value: T) -> syn::Result<()> {
65        let tokens = obj.into_token_stream();
66        if self.value.is_some() {
67            Err(Error::new(
68                tokens.span(),
69                format!("duplicate value: {}", self.name),
70            ))
71        } else {
72            self.tokens = tokens;
73            self.value = Some(value);
74            Ok(())
75        }
76    }
77
78    /// Returns the inner value.
79    pub fn get(self) -> Option<T> {
80        self.value
81    }
82}