/src/gitoxide/gix-attributes/src/search/mod.rs
Line | Count | Source |
1 | | use std::collections::HashMap; |
2 | | |
3 | | use gix_features::threading::OwnShared; |
4 | | use smallvec::SmallVec; |
5 | | |
6 | | use crate::{Assignment, AssignmentRef, Name}; |
7 | | |
8 | | mod attributes; |
9 | | mod outcome; |
10 | | mod refmap; |
11 | | pub(crate) use refmap::RefMap; |
12 | | |
13 | | /// A typically sized list of attributes. |
14 | | pub type Assignments = SmallVec<[TrackedAssignment; AVERAGE_NUM_ATTRS]>; |
15 | | |
16 | | /// A value of a [pattern mapping][gix_glob::search::pattern::Mapping], |
17 | | /// which is either a macro definition or a set of attributes. |
18 | | #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] |
19 | | pub enum Value { |
20 | | /// A macro, whose name resolves to the contained assignments. Note that the name is the pattern of the mapping itself. |
21 | | MacroAssignments { |
22 | | /// The id of the macro itself, which is both an attribute as well as a set of additional attributes into which the macro |
23 | | /// resolves |
24 | | id: AttributeId, |
25 | | /// The attributes or assignments that the macro resolves to. |
26 | | assignments: Assignments, |
27 | | }, |
28 | | /// A set of assignments which are the attributes themselves. |
29 | | Assignments(Assignments), |
30 | | } |
31 | | |
32 | | /// A way to have an assignment (`attr=value`) but also associated it with an id that allows perfect mapping |
33 | | /// to tracking information. |
34 | | /// Note that the order is produced after the files are parsed as global ordering is needed that goes beyond the scope of a |
35 | | /// single `Search` instance. |
36 | | #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] |
37 | | pub struct TrackedAssignment { |
38 | | /// The order of the assignment. |
39 | | pub id: AttributeId, |
40 | | /// The actual assignment information. |
41 | | pub inner: Assignment, |
42 | | } |
43 | | |
44 | | /// An implementation of the [`Pattern`][gix_glob::search::Pattern] trait for attributes. |
45 | | #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Default)] |
46 | | pub struct Attributes; |
47 | | |
48 | | /// Describes a matching pattern with |
49 | | #[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)] |
50 | | pub struct Match<'a> { |
51 | | /// The glob pattern itself, like `/target/*`. |
52 | | pub pattern: &'a gix_glob::Pattern, |
53 | | /// The key=value pair of the attribute that matched at the pattern. There can be multiple matches per pattern. |
54 | | pub assignment: AssignmentRef<'a>, |
55 | | /// Additional information about the kind of match. |
56 | | pub kind: MatchKind, |
57 | | /// Information about the location of the match. |
58 | | pub location: MatchLocation<'a>, |
59 | | } |
60 | | |
61 | | /// Describes in which what file and line the match was found. |
62 | | #[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)] |
63 | | pub struct MatchLocation<'a> { |
64 | | /// The path to the source from which the pattern was loaded, or `None` if it was specified by other means. |
65 | | pub source: Option<&'a std::path::Path>, |
66 | | /// The line at which the pattern was found in its `source` file, or the occurrence in which it was provided. |
67 | | pub sequence_number: usize, |
68 | | } |
69 | | |
70 | | /// The kind of attribute within the context of a [match][Match]. |
71 | | #[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)] |
72 | | pub enum MatchKind { |
73 | | /// A attribute. |
74 | | Attribute { |
75 | | /// The location of the macro which referred to it the list with all in-order attributes and macros, or `None` if |
76 | | /// this is attribute wasn't resolved. |
77 | | /// |
78 | | /// Use [`Outcome::match_by_id()`] to retrieve the macro. |
79 | | macro_id: Option<AttributeId>, |
80 | | }, |
81 | | /// The attribute is a macro, which will resolve into one or more attributes or macros. |
82 | | Macro { |
83 | | /// The location of the parent macro which referred to this one in the list with all in-order attributes and macros, |
84 | | /// or `None` if this is macro wasn't resolved by another one. |
85 | | /// |
86 | | /// Use [`Outcome::match_by_id()`] to retrieve the parent. |
87 | | parent_macro_id: Option<AttributeId>, |
88 | | }, |
89 | | } |
90 | | |
91 | | /// The result of a search, containing all matching attributes. |
92 | | #[derive(Default, Clone)] |
93 | | pub struct Outcome { |
94 | | /// The list of all available attributes, by ascending order. Each slots index corresponds to an attribute with that order, i.e. |
95 | | /// `arr[attr.id] = <attr info>`. |
96 | | /// |
97 | | /// This list needs to be up-to-date with the search group so all possible attribute names are known. |
98 | | matches_by_id: Vec<Slot>, |
99 | | /// A stack of attributes to use for processing attributes of matched patterns and for resolving their macros. |
100 | | attrs_stack: SmallVec<[(AttributeId, Assignment, Option<AttributeId>); 8]>, |
101 | | /// A set of attributes we should limit ourselves to, or empty if we should fill in all attributes, made of |
102 | | selected: SmallVec<[(OwnShared<str>, Option<AttributeId>); AVERAGE_NUM_ATTRS]>, |
103 | | /// storage for all patterns we have matched so far (in order to avoid referencing them, we copy them, but only once). |
104 | | patterns: RefMap<gix_glob::Pattern>, |
105 | | /// storage for all assignments we have matched so far (in order to avoid referencing them, we copy them, but only once). |
106 | | assignments: RefMap<Assignment>, |
107 | | /// storage for all source paths we have matched so far (in order to avoid referencing them, we copy them, but only once). |
108 | | source_paths: RefMap<std::path::PathBuf>, |
109 | | /// The amount of attributes that still need to be set, or `None` if this outcome is consumed which means it |
110 | | /// needs to be re-initialized. |
111 | | remaining: Option<usize>, |
112 | | } |
113 | | |
114 | | #[derive(Default, Clone)] |
115 | | struct Slot { |
116 | | r#match: Option<outcome::Match>, |
117 | | /// A list of all assignments, being an empty list for non-macro attributes, or all assignments (with order) for macros. |
118 | | /// It's used to resolve macros. |
119 | | macro_attributes: Assignments, |
120 | | } |
121 | | |
122 | | /// A type to denote an id of an attribute assignment for uniquely identifying each attribute or assignment. |
123 | | #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)] |
124 | | pub struct AttributeId(pub usize); |
125 | | |
126 | | impl Default for AttributeId { |
127 | 18.0k | fn default() -> Self { |
128 | 18.0k | AttributeId(usize::MAX) |
129 | 18.0k | } Unexecuted instantiation: <gix_attributes::search::AttributeId as core::default::Default>::default <gix_attributes::search::AttributeId as core::default::Default>::default Line | Count | Source | 127 | 18.0k | fn default() -> Self { | 128 | 18.0k | AttributeId(usize::MAX) | 129 | 18.0k | } |
|
130 | | } |
131 | | |
132 | | /// A utility type to collect metadata for each attribute, unified by its name. |
133 | | #[derive(Clone, Debug, Default)] |
134 | | pub struct MetadataCollection { |
135 | | /// A mapping of an attribute or macro name to its order, that is the time when it was *first* seen. |
136 | | /// |
137 | | /// This is the inverse of the order attributes are searched. |
138 | | name_to_meta: HashMap<Name, Metadata>, |
139 | | } |
140 | | |
141 | | /// Metadata associated with an attribute or macro name. |
142 | | #[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)] |
143 | | pub struct Metadata { |
144 | | /// The id to uniquely identify an attribute in the [MetadataCollection]. |
145 | | pub id: AttributeId, |
146 | | /// If non-zero in length, this entry belongs to a macro which resolves to these attribute names. |
147 | | pub macro_attributes: Assignments, |
148 | | } |
149 | | |
150 | | const AVERAGE_NUM_ATTRS: usize = 3; |