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 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
use kstring::KString;
use smallvec::SmallVec;
use std::collections::HashMap;
use crate::{Assignment, AssignmentRef};
mod attributes;
mod outcome;
mod refmap;
pub(crate) use refmap::RefMap;
/// A typically sized list of attributes.
pub type Assignments = SmallVec<[TrackedAssignment; AVERAGE_NUM_ATTRS]>;
/// A value of a [pattern mapping][gix_glob::search::pattern::Mapping],
/// which is either a macro definition or a set of attributes.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub enum Value {
/// A macro, whose name resolves to the contained assignments. Note that the name is the pattern of the mapping itself.
MacroAssignments {
/// The id of the macro itself, which is both an attribute as well as a set of additional attributes into which the macro
/// resolves
id: AttributeId,
/// The attributes or assignments that the macro resolves to.
assignments: Assignments,
},
/// A set of assignments which are the attributes themselves.
Assignments(Assignments),
}
/// A way to have an assignment (`attr=value`) but also associated it with an id that allows perfect mapping
/// to tracking information.
/// Note that the order is produced after the files are parsed as global ordering is needed that goes beyond the scope of a
/// single `Search` instance.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub struct TrackedAssignment {
/// The order of the assignment.
pub id: AttributeId,
/// The actual assignment information.
pub inner: Assignment,
}
/// An implementation of the [`Pattern`][gix_glob::search::Pattern] trait for attributes.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Default)]
pub struct Attributes;
/// Describes a matching pattern with
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct Match<'a> {
/// The glob pattern itself, like `/target/*`.
pub pattern: &'a gix_glob::Pattern,
/// The key=value pair of the attribute that matched at the pattern. There can be multiple matches per pattern.
pub assignment: AssignmentRef<'a>,
/// Additional information about the kind of match.
pub kind: MatchKind,
/// Information about the location of the match.
pub location: MatchLocation<'a>,
}
/// Describes in which what file and line the match was found.
#[derive(Clone, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub struct MatchLocation<'a> {
/// The path to the source from which the pattern was loaded, or `None` if it was specified by other means.
pub source: Option<&'a std::path::Path>,
/// The line at which the pattern was found in its `source` file, or the occurrence in which it was provided.
pub sequence_number: usize,
}
/// The kind of attribute within the context of a [match][Match].
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Ord, PartialOrd)]
pub enum MatchKind {
/// A attribute.
Attribute {
/// The location of the macro which referred to it the list with all in-order attributes and macros, or `None` if
/// this is attribute wasn't resolved.
///
/// Use [`Outcome::match_by_id()`] to retrieve the macro.
macro_id: Option<AttributeId>,
},
/// The attribute is a macro, which will resolve into one or more attributes or macros.
Macro {
/// The location of the parent macro which referred to this one in the list with all in-order attributes and macros,
/// or `None` if this is macro wasn't resolved by another one.
///
/// Use [`Outcome::match_by_id()`] to retrieve the parent.
parent_macro_id: Option<AttributeId>,
},
}
/// The result of a search, containing all matching attributes.
#[derive(Default, Clone)]
pub struct Outcome {
/// The list of all available attributes, by ascending order. Each slots index corresponds to an attribute with that order, i.e.
/// `arr[attr.id] = <attr info>`.
///
/// This list needs to be up-to-date with the search group so all possible attribute names are known.
matches_by_id: Vec<Slot>,
/// A stack of attributes to use for processing attributes of matched patterns and for resolving their macros.
attrs_stack: SmallVec<[(AttributeId, Assignment, Option<AttributeId>); 8]>,
/// A set of attributes we should limit ourselves to, or empty if we should fill in all attributes, made of
selected: SmallVec<[(KString, Option<AttributeId>); AVERAGE_NUM_ATTRS]>,
/// storage for all patterns we have matched so far (in order to avoid referencing them, we copy them, but only once).
patterns: RefMap<gix_glob::Pattern>,
/// storage for all assignments we have matched so far (in order to avoid referencing them, we copy them, but only once).
assignments: RefMap<Assignment>,
/// storage for all source paths we have matched so far (in order to avoid referencing them, we copy them, but only once).
source_paths: RefMap<std::path::PathBuf>,
/// The amount of attributes that still need to be set, or `None` if this outcome is consumed which means it
/// needs to be re-initialized.
remaining: Option<usize>,
}
#[derive(Default, Clone)]
struct Slot {
r#match: Option<outcome::Match>,
/// A list of all assignments, being an empty list for non-macro attributes, or all assignments (with order) for macros.
/// It's used to resolve macros.
macro_attributes: Assignments,
}
/// A type to denote an id of an attribute assignment for uniquely identifying each attribute or assignment.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
pub struct AttributeId(pub usize);
impl Default for AttributeId {
fn default() -> Self {
AttributeId(usize::MAX)
}
}
/// A utility type to collect metadata for each attribute, unified by its name.
#[derive(Clone, Debug, Default)]
pub struct MetadataCollection {
/// A mapping of an attribute or macro name to its order, that is the time when it was *first* seen.
///
/// This is the inverse of the order attributes are searched.
name_to_meta: HashMap<KString, Metadata>,
}
/// Metadata associated with an attribute or macro name.
#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone)]
pub struct Metadata {
/// The id to uniquely identify an attribute in the [MetadataCollection].
pub id: AttributeId,
/// If non-zero in length, this entry belongs to a macro which resolves to these attribute names.
pub macro_attributes: Assignments,
}
const AVERAGE_NUM_ATTRS: usize = 3;