Skip to content

Commit

Permalink
[wip] Introduce Treeish for native roots and patterns.
Browse files Browse the repository at this point in the history
  • Loading branch information
olson-sean-k committed Oct 4, 2023
1 parent 1afcda8 commit 657dcea
Show file tree
Hide file tree
Showing 3 changed files with 199 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ mod diagnostics;
mod encode;
mod rule;
mod token;
mod treeish;
mod walk;

#[cfg(feature = "miette")]
Expand Down
170 changes: 170 additions & 0 deletions src/treeish/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
mod parse;

use std::borrow::Cow;
use std::ops::Deref;
use std::path::Path;

use crate::Glob;

pub use crate::treeish::parse::parse;

// TODO: It is probably possible to implement this in a separate crate!

// TODO: Syntax like this:
//
// `C:\Users::**/*.txt`
// `/mnt/media1::**/*.txt`
//
// This uses `::` as the separator. Consider `>>`.

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct Unrooted<T>(T);

impl<T> Unrooted<T> {
fn map<U, F>(self, f: F) -> Unrooted<U>

Check warning on line 25 in src/treeish/mod.rs

View workflow job for this annotation

GitHub Actions / Lint

method `map` is never used
where
F: FnOnce(T) -> U,
{
Unrooted(f(self.0))
}
}

impl<'t> Unrooted<TreeishGlob<'t>> {
pub fn into_owned(self) -> Unrooted<TreeishGlob<'static>> {

Check warning on line 34 in src/treeish/mod.rs

View workflow job for this annotation

GitHub Actions / Lint

method `into_owned` is never used
self.map(TreeishGlob::into_owned)
}
}

impl<T> AsRef<T> for Unrooted<T> {
fn as_ref(&self) -> &T {
&self.0
}
}

impl<T> Deref for Unrooted<T> {
type Target = T;

fn deref(&self) -> &Self::Target {
&self.0
}
}

#[derive(Clone, Debug, Eq, PartialEq)]
#[repr(transparent)]
pub struct TreeishPath<'p>(Cow<'p, Path>);

impl<'p> TreeishPath<'p> {
pub fn into_owned(self) -> TreeishPath<'static> {
TreeishPath(self.0.into_owned().into())
}

pub fn as_ref(&'p self) -> &'p Path {
self.0.as_ref()
}
}

impl<'p> Deref for TreeishPath<'p> {
type Target = Cow<'p, Path>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<'p> From<TreeishPath<'p>> for Cow<'p, Path> {
fn from(path: TreeishPath<'p>) -> Self {
path.0
}
}

#[derive(Clone, Debug)]
#[repr(transparent)]
pub struct TreeishGlob<'t>(Glob<'t>);

impl<'t> TreeishGlob<'t> {
pub fn into_owned(self) -> TreeishGlob<'static> {
TreeishGlob(self.0.into_owned())
}
}

impl<'t> AsRef<Glob<'t>> for TreeishGlob<'t> {
fn as_ref(&self) -> &Glob<'t> {
&self.0
}
}

impl<'t> Deref for TreeishGlob<'t> {
type Target = Glob<'t>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl<'t> From<TreeishGlob<'t>> for Glob<'t> {
fn from(glob: TreeishGlob<'t>) -> Self {
glob.0
}
}

// TODO: What about "empty"? Arguably, path-like structures should not provide an intrinsic
// representation of empty, like `Path("")`. Instead, an extrinsic representation like `None`
// should be used and types like `Path` should **never** represent "nothing". `Treeish`
// should do the same, and APIs should probably be fallible (or if not conceptually
// "fallible" still yield `Option<Treeish>`).
pub enum Treeish<'t> {
Path(TreeishPath<'t>),

Check warning on line 117 in src/treeish/mod.rs

View workflow job for this annotation

GitHub Actions / Lint

variant `Path` is never constructed
Pattern(TreeishGlob<'t>),
PatternIn {
tree: TreeishPath<'t>,
glob: Unrooted<TreeishGlob<'t>>,
},
}

impl<'t> Treeish<'t> {
pub fn into_owned(self) -> Treeish<'static> {
use Treeish::{Path, Pattern, PatternIn};

match self {
Path(path) => Path(path.into_owned()),
Pattern(glob) => Pattern(glob.into_owned()),
PatternIn { tree, glob } => PatternIn {
tree: tree.into_owned(),
glob: glob.into_owned(),
},
}
}

pub fn walk(&self) -> () {

Check failure on line 139 in src/treeish/mod.rs

View workflow job for this annotation

GitHub Actions / Lint

unneeded unit return type
todo!()
}

pub fn is_semantic_match(&self, _: ()) -> bool {
todo!()
}
}

impl<'t> TryFrom<Glob<'t>> for Treeish<'t> {
type Error = ();

fn try_from(glob: Glob<'t>) -> Result<Self, Self::Error> {
// TODO: This conversion does not handle an "empty" glob and there is no (good) way to
// determine if a glob is empty or not. `Glob::partition` should probably provide a
// better API for this!
let (path, glob) = glob.partition();
if glob.has_root() {
return Err(());
}
let glob = TreeishGlob(glob);
Ok(if path.as_os_str().is_empty() {
Treeish::Pattern(glob)
}
else {
Treeish::PatternIn {
tree: TreeishPath(path.into()),
glob: Unrooted(glob),
}
})
}
}
28 changes: 28 additions & 0 deletions src/treeish/parse.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use nom::error::{VerboseError as NomError, VerboseErrorKind as NomErrorKind};

Check warning on line 1 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused import: `VerboseErrorKind as NomErrorKind`

use crate::token::{self, ParseError as GlobParseError};

Check warning on line 3 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused import: `self`
use crate::treeish::Treeish;

type Input<'i> = &'i str;
type ErrorStack<'i> = NomError<Input<'i>>;
type ErrorMode<'i> = nom::Err<ErrorStack<'i>>;

pub struct ParseError<'t> {
kind: ParseErrorKind<'t>,
}

enum ParseErrorKind<'t> {
Glob(GlobParseError<'t>),
Treeish,
}

pub fn parse(expression: &str) -> Result<Treeish, ParseError> {

Check warning on line 19 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused variable: `expression`
use nom::bytes::complete as bytes;

Check warning on line 20 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused import: `nom::bytes::complete as bytes`
use nom::character::complete as character;

Check warning on line 21 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused import: `nom::character::complete as character`
use nom::error;

Check warning on line 22 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused import: `nom::error`
use nom::{branch, combinator, multi, sequence, IResult, Parser};

Check warning on line 23 in src/treeish/parse.rs

View workflow job for this annotation

GitHub Actions / Lint

unused imports: `Parser`, `branch`, `combinator`, `multi`, `sequence`

type ParseResult<'i, O> = IResult<Input<'i>, O, ErrorStack<'i>>;

todo!()
}

0 comments on commit 657dcea

Please sign in to comment.