swamp_attributes/
lib.rs

1/*
2 * Copyright (c) Peter Bjorklund. All rights reserved. https://github.com/swamp/swamp
3 * Licensed under the MIT License. See LICENSE in the project root for license information.
4 */
5
6use source_map_node::Node;
7
8#[derive(Debug, Clone, Default)]
9pub struct Attributes(pub Vec<Attribute>);
10
11impl Attributes {
12    #[must_use]
13    pub fn get_attributes(&self, name: &str) -> Self {
14        let vec: Vec<_> = self
15            .0
16            .iter()
17            .filter(|attr| attr.path.name == name)
18            .cloned()
19            .collect();
20
21        Self(vec)
22    }
23
24    #[must_use]
25    pub const fn is_empty(&self) -> bool {
26        self.0.is_empty()
27    }
28
29    #[must_use]
30    pub fn has_attribute(&self, name: &str) -> bool {
31        self.0.iter().any(|attr| attr.path.name == name)
32    }
33
34    #[must_use]
35    pub fn get_attribute(&self, name: &str) -> Option<&Attribute> {
36        self.0.iter().find(|attr| attr.path.name == name)
37    }
38
39    #[must_use]
40    pub fn get_fn_arg_by_name(&self, attr_name: &str, arg_fn_name: &str) -> Option<&AttributeArg> {
41        self.get_attribute(attr_name).and_then(|attr| {
42            attr.args.iter().find(|arg| {
43                if let AttributeArg::Function(id, _) = arg {
44                    id.name == arg_fn_name
45                } else {
46                    false
47                }
48            })
49        })
50    }
51
52    #[must_use]
53    pub fn get_fn_arg_sub_args(
54        &self,
55        attr_name: &str,
56        arg_fn_name: &str,
57    ) -> Option<&Vec<AttributeArg>> {
58        self.get_fn_arg_by_name(attr_name, arg_fn_name)
59            .and_then(|arg| {
60                if let AttributeArg::Function(_, sub_args) = arg {
61                    Some(sub_args)
62                } else {
63                    None // This should ideally not happen if `get_fn_arg_by_name` already filtered for Function
64                }
65            })
66    }
67
68    #[must_use]
69    pub fn get_arg(&self, name: &str, arg_index: usize) -> Option<AttributeArg> {
70        self.get_args(name)
71            .and_then(|a| Option::from(a[arg_index].clone()))
72    }
73
74    #[must_use]
75    pub fn get_value(&self, name: &str, arg_index: usize) -> Option<AttributeValue> {
76        self.get_arg(name, arg_index).and_then(|arg| match arg {
77            AttributeArg::Literal(x) => Some(x),
78            _ => None,
79        })
80    }
81
82    #[must_use]
83    pub fn get_int(&self, name: &str, arg_index: usize) -> Option<i32> {
84        self.get_value(name, arg_index).and_then(|x| match x {
85            AttributeValue::Int(v) => Some(v),
86            _ => None,
87        })
88    }
89    #[must_use]
90    pub fn get_int_from_fn_arg(
91        &self,
92        attr_name: &str,
93        arg_fn_name: &str,
94        sub_arg_index: usize,
95    ) -> Option<i32> {
96        self.get_fn_arg_sub_args(attr_name, arg_fn_name)
97            .and_then(|sub_args| {
98                sub_args
99                    .get(sub_arg_index)
100                    .and_then(|sub_arg| match sub_arg {
101                        AttributeArg::Literal(attr_value) => match attr_value {
102                            AttributeValue::Int(v) => Some(*v),
103                            _ => None,
104                        },
105                        _ => None,
106                    })
107            })
108    }
109
110    #[must_use]
111    pub fn get_string_from_fn_arg(
112        &self,
113        attr_name: &str,
114        arg_fn_name: &str,
115        sub_arg_index: usize,
116    ) -> Option<&String> {
117        self.get_fn_arg_sub_args(attr_name, arg_fn_name)
118            .and_then(|sub_args| {
119                sub_args
120                    .get(sub_arg_index)
121                    .and_then(|sub_arg| match sub_arg {
122                        AttributeArg::Literal(attr_value) => match attr_value {
123                            AttributeValue::String(s) => Some(s),
124                            _ => None,
125                        },
126                        _ => None,
127                    })
128            })
129    }
130
131    #[must_use]
132    pub fn get_string(&self, name: &str, arg_index: usize) -> Option<String> {
133        self.get_value(name, arg_index).and_then(|x| match x {
134            AttributeValue::String(v) => Some(v),
135            _ => None,
136        })
137    }
138    #[must_use]
139    pub fn get_args(&self, name: &str) -> Option<Vec<AttributeArg>> {
140        self.get_attribute(name)
141            .and_then(|a| Option::from(a.args.clone()))
142    }
143}
144
145#[derive(Debug, Clone)]
146pub struct Attribute {
147    pub path: AttributeIdentifier,
148    pub args: Vec<AttributeArg>,
149    pub node: Node,
150}
151
152#[derive(Debug, Clone)]
153pub struct AttributeIdentifier {
154    pub name: String,
155}
156
157#[derive(Debug, Clone)]
158pub enum AttributeArg {
159    Path(AttributeIdentifier), // e.g., Debug, unix, clippy::something
160    Literal(AttributeValue),   // e.g., "foo", 42, true
161    Function(AttributeIdentifier, Vec<AttributeArg>), // e.g., any(unix, windows)
162}
163
164#[derive(Debug, Clone)]
165pub enum AttributeValue {
166    String(String),
167    Int(i32),
168    Bool(bool),
169}