Skip to content

Commit

Permalink
Export more types in query.
Browse files Browse the repository at this point in the history
  • Loading branch information
olson-sean-k committed Mar 16, 2024
1 parent a2f8764 commit 1a9f767
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 13 deletions.
5 changes: 4 additions & 1 deletion src/query.rs
@@ -1,6 +1,9 @@
use crate::diagnostics::Span;

pub use crate::token::{BoundedVariantRange, Boundedness, Depth, Text, UnitBound, Variance};
pub use crate::token::{
BoundedVariantRange, Boundedness, Depth, GlobVariance, Invariant, Text, UnitBound, Variance,
VariantRange,
};

#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub enum When {
Expand Down
4 changes: 3 additions & 1 deletion src/token/mod.rs
Expand Up @@ -21,7 +21,9 @@ use crate::token::walk::{BranchFold, Fold, FoldMap, Starting, TokenEntry};
use crate::{StrExt as _, PATHS_ARE_CASE_INSENSITIVE};

pub use crate::token::parse::{parse, ParseError, ROOT_SEPARATOR_EXPRESSION};
pub use crate::token::variance::bound::{BoundedVariantRange, Boundedness, NaturalRange};
pub use crate::token::variance::bound::{
BoundedVariantRange, Boundedness, NaturalRange, VariantRange,
};
pub use crate::token::variance::invariant::{Breadth, Depth, Invariant, Size, Text, UnitBound};
pub use crate::token::variance::{GlobVariance, Variance};

Expand Down
10 changes: 8 additions & 2 deletions src/token/variance/invariant/text.rs
Expand Up @@ -65,7 +65,7 @@ pub struct Text<'t> {
}

impl<'t> Text<'t> {
pub(crate) fn new() -> Self {
pub fn new() -> Self {
Text {
fragments: VecDeque::new(),
}
Expand Down Expand Up @@ -106,7 +106,7 @@ impl<'t> Text<'t> {
.unwrap_or(Cow::Borrowed(""))
}

pub(crate) fn repeated(self, n: NonZeroUsize) -> Self {
fn repeated(self, n: NonZeroUsize) -> Self {
let Text { fragments } = self;
let n = (usize::from(n) - 1)
.checked_mul(fragments.len())
Expand Down Expand Up @@ -152,6 +152,12 @@ impl<'t> Conjunction<Fragment<'t>> for Text<'t> {
}
}

impl<'t> Default for Text<'t> {
fn default() -> Self {
Text::new()
}
}

impl<'t> From<Fragment<'t>> for Text<'t> {
fn from(fragment: Fragment<'t>) -> Self {
Text {
Expand Down
18 changes: 18 additions & 0 deletions src/token/variance/mod.rs
Expand Up @@ -106,6 +106,24 @@ impl<T, B> Variance<T, B> {
}
}

impl<T> Variance<T, T> {
pub fn into_inner(self) -> T {
match self {
Variance::Invariant(inner) | Variance::Variant(inner) => inner,
}
}

pub fn map<U, F>(self, f: F) -> Variance<U, U>
where
F: FnOnce(T) -> U,
{
match self {
Variance::Invariant(invariant) => Variance::Invariant(f(invariant)),
Variance::Variant(variant) => Variance::Variant(f(variant)),
}
}
}

impl<T, B> Variance<T, Boundedness<B>> {
pub const fn unbounded() -> Self {
Variance::Variant(Unbounded)
Expand Down
22 changes: 19 additions & 3 deletions src/walk/behavior.rs
@@ -1,5 +1,7 @@
use std::num::NonZeroUsize;

use crate::token::{Depth, GlobVariance};

/// Configuration for a minimum depth of matched files in a walk.
///
/// Unlike a maximum depth, a minimum depth cannot be zero, because such a minimum has no effect.
Expand Down Expand Up @@ -162,9 +164,6 @@ pub enum DepthBehavior {
}

impl DepthBehavior {
// TODO: Provide a similar function for `Glob`s called something like
// `bounded_with_depth_variance`, which additionally accepts a depth variance and
// considers this variance when constructing the `DepthBehavior`.
/// Constructs a bounded `DepthBehavior` from a minimum and/or maximum depth.
///
/// This function provides an ergonomic way to place bounds on the depth of a walk. At least
Expand Down Expand Up @@ -210,6 +209,23 @@ impl DepthBehavior {
_ => None,
}
}

pub fn bounded_with_depth_variance(
min: impl Into<Option<usize>>,
max: impl Into<Option<usize>>,
depth: GlobVariance<Depth>,
) -> Option<Self> {
let lower = depth
.map_invariant(From::from)
.map_variant(|bound| bound.lower().into_usize())
.into_inner();
let translation = move |depth: Option<usize>| -> Result<Option<usize>, ()> {
depth
.map(|depth| depth.checked_add(lower).ok_or(()))
.transpose()
};
DepthBehavior::bounded(translation(min.into()).ok()?, translation(max.into()).ok()?)
}
}

impl From<DepthMax> for DepthBehavior {
Expand Down
8 changes: 4 additions & 4 deletions src/walk/glob.rs
Expand Up @@ -26,9 +26,9 @@ impl<'t> Glob<'t> {
/// directory trees.
///
/// As with [`Path::join`] and [`PathBuf::push`], the base directory can be escaped or
/// overridden by [a `Glob` that has a root][`has_root`]. In many cases, the current working
/// directory `.` is an appropriate base directory and will be intuitively ignored if the
/// `Glob` is rooted, such as in `/mnt/media/**/*.mp4`.
/// overridden by [a `Glob` that has a root][`Program::has_root`]. In many cases, the current
/// working directory `.` is an appropriate base directory and will be intuitively ignored if
/// the `Glob` is rooted, such as in `/mnt/media/**/*.mp4`.
///
/// The [root path segment][`Entry::root_relative_paths`] is either the given directory or, if
/// the `Glob` has a root, the [invariant prefix][`Glob::partition`] of the `Glob`. Either way,
Expand Down Expand Up @@ -82,13 +82,13 @@ impl<'t> Glob<'t> {
/// [`Entry::root_relative_paths`]: crate::walk::Entry::root_relative_paths
/// [`Glob::walk_with_behavior`]: crate::Glob::walk_with_behavior
/// [`GlobEntry`]: crate::walk::GlobEntry
/// [`has_root`]: crate::Glob::has_root
/// [`FileIterator`]: crate::walk::FileIterator
/// [`Iterator::filter`]: std::iter::Iterator::filter
/// [`not`]: crate::walk::FileIterator::not
/// [`Path::join`]: std::path::Path::join
/// [`PathBuf::push`]: std::path::PathBuf::push
/// [`Program`]: crate::Program
/// [`Program::has_root`]: crate::Program::has_root
/// [`Program::is_exhaustive`]: crate::Program::is_exhaustive
/// [`WalkBehavior`]: crate::walk::WalkBehavior
pub fn walk(&self, path: impl Into<PathBuf>) -> impl 'static + FileIterator<Entry = GlobEntry> {
Expand Down
4 changes: 2 additions & 2 deletions src/walk/mod.rs
Expand Up @@ -315,18 +315,18 @@ pub trait Entry {
/// The root segment is the path from which the walk started. When walking a [`Path`] via
/// functions in [`PathExt`], the root is always the same as the path itself. When walking a
/// pattern like [`Glob`], the root segment differs depending on whether or not the pattern
/// [has a root][`Glob::has_root`]. If a pattern has a root, then the root segment is the
/// [has a root][`Program::has_root`]. If a pattern has a root, then the root segment is the
/// invariant prefix in the pattern, otherwise the root segment is the path given to functions
/// like [`Glob::walk`].
///
/// The relative segment is the remainder (descendant) of the path of the file (relative to the
/// root segment).
///
/// [`Glob`]: crate::Glob
/// [`Glob::has_root`]: crate::Glob::has_root
/// [`Glob::walk`]: crate::Glob::walk
/// [`Path`]: std::path::Path
/// [`PathExt`]: crate::walk::PathExt
/// [`Program::has_root`]: crate::Program::has_root
fn root_relative_paths(&self) -> (&Path, &Path);

/// Gets the [`Metadata`] of the file.
Expand Down

0 comments on commit 1a9f767

Please sign in to comment.