gix_attributes/search/
mod.rs

1use std::collections::HashMap;
2
3use kstring::KString;
4use smallvec::SmallVec;
5
6use crate::{Assignment, AssignmentRef};
7
8mod attributes;
9mod outcome;
10mod refmap;
11pub(crate) use refmap::RefMap;
12
13/// A typically sized list of attributes.
14pub 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)]
19pub 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)]
37pub 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)]
46pub struct Attributes;
47
48/// Describes a matching pattern with
49#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
50pub 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)]
63pub 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)]
72pub 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)]
93pub 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<[(KString, 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)]
115struct 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)]
124pub struct AttributeId(pub usize);
125
126impl Default for AttributeId {
127    fn default() -> Self {
128        AttributeId(usize::MAX)
129    }
130}
131
132/// A utility type to collect metadata for each attribute, unified by its name.
133#[derive(Clone, Debug, Default)]
134pub 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<KString, Metadata>,
139}
140
141/// Metadata associated with an attribute or macro name.
142#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
143pub 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
150const AVERAGE_NUM_ATTRS: usize = 3;