Skip to content

Commit

Permalink
chore!: scopes into new module
Browse files Browse the repository at this point in the history
  • Loading branch information
alexpovel committed Oct 24, 2023
1 parent 0e00f43 commit e951347
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 88 deletions.
91 changes: 3 additions & 88 deletions src/scoping/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ use crate::actions::{self, Action};

use self::literal::LiteralError;
use self::regex::RegexError;
use itertools::Itertools;
use self::scope::{ROScope, ROScopes, RWScope, RWScopes, Scope};
use log::{debug, trace};
use std::borrow::Cow;
use std::fmt;
use std::{borrow::Cow, ops::Range};

pub mod langs;
pub mod literal;
pub mod regex;
pub mod scope;

#[derive(Debug)]
pub enum ScoperBuildError {
Expand All @@ -32,60 +33,6 @@ impl From<RegexError> for ScoperBuildError {
}
}

/// Indicates whether a given string part is in scope.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Scope<'viewee, T> {
/// The given part is in scope for processing.
In(T),
/// The given part is out of scope for processing.
///
/// Treated as immutable, view-only.
Out(&'viewee str),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ROScope<'viewee>(pub Scope<'viewee, &'viewee str>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ROScopes<'viewee>(pub Vec<ROScope<'viewee>>);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RWScope<'viewee>(pub Scope<'viewee, Cow<'viewee, str>>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RWScopes<'viewee>(pub Vec<RWScope<'viewee>>);

impl<'viewee> ROScope<'viewee> {
/// Check whether the scope is empty.
#[must_use]
pub fn is_empty(&self) -> bool {
let s: &str = self.into();
s.is_empty()
}
}

impl<'viewee> ROScopes<'viewee> {
#[must_use]
pub fn from_raw_ranges(input: &'viewee str, ranges: Vec<Range<usize>>) -> Self {
let mut scopes = Vec::with_capacity(ranges.len());

let mut last_end = 0;
for Range { start, end } in ranges.into_iter().sorted_by_key(|r| r.start) {
scopes.push(ROScope(Scope::Out(&input[last_end..start])));
scopes.push(ROScope(Scope::In(&input[start..end])));
last_end = end;
}

if last_end < input.len() {
scopes.push(ROScope(Scope::Out(&input[last_end..])));
}

scopes.retain(|s| !s.is_empty());

debug!("Scopes: {:?}", scopes);

ROScopes(scopes)
}
}

pub trait Scoper {
fn scope<'viewee>(&self, input: &'viewee str) -> ROScopes<'viewee>;
}
Expand All @@ -96,38 +43,6 @@ impl fmt::Debug for dyn Scoper {
}
}

impl<'viewee> From<&'viewee ROScope<'viewee>> for &'viewee str {
/// Get the underlying string slice.
///
/// All variants contain such a slice, so this is a convenient method.
fn from(s: &'viewee ROScope) -> Self {
match s.0 {
Scope::In(s) | Scope::Out(s) => s,
}
}
}

impl<'viewee> From<ROScope<'viewee>> for RWScope<'viewee> {
fn from(s: ROScope<'viewee>) -> Self {
match s.0 {
Scope::In(s) => RWScope(Scope::In(Cow::Borrowed(s))),
Scope::Out(s) => RWScope(Scope::Out(s)),
}
}
}

impl<'viewee> From<&'viewee RWScope<'viewee>> for &'viewee str {
/// Get the underlying string slice.
///
/// All variants contain such a slice, so this is a convenient method.
fn from(s: &'viewee RWScope) -> Self {
match &s.0 {
Scope::In(s) => s,
Scope::Out(s) => s,
}
}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ScopedViewBuilder<'viewee> {
scopes: ROScopes<'viewee>,
Expand Down
89 changes: 89 additions & 0 deletions src/scoping/scope.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use itertools::Itertools;
use log::debug;
use std::{borrow::Cow, ops::Range};

/// Indicates whether a given string part is in scope.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Scope<'viewee, T> {
/// The given part is in scope for processing.
In(T),
/// The given part is out of scope for processing.
///
/// Treated as immutable, view-only.
Out(&'viewee str),
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ROScope<'viewee>(pub Scope<'viewee, &'viewee str>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ROScopes<'viewee>(pub Vec<ROScope<'viewee>>);

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RWScope<'viewee>(pub Scope<'viewee, Cow<'viewee, str>>);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RWScopes<'viewee>(pub Vec<RWScope<'viewee>>);

impl<'viewee> ROScope<'viewee> {
/// Check whether the scope is empty.
#[must_use]
pub fn is_empty(&self) -> bool {
let s: &str = self.into();
s.is_empty()
}
}

impl<'viewee> ROScopes<'viewee> {
#[must_use]
pub fn from_raw_ranges(input: &'viewee str, ranges: Vec<Range<usize>>) -> Self {
let mut scopes = Vec::with_capacity(ranges.len());

let mut last_end = 0;
for Range { start, end } in ranges.into_iter().sorted_by_key(|r| r.start) {
scopes.push(ROScope(Scope::Out(&input[last_end..start])));
scopes.push(ROScope(Scope::In(&input[start..end])));
last_end = end;
}

if last_end < input.len() {
scopes.push(ROScope(Scope::Out(&input[last_end..])));
}

scopes.retain(|s| !s.is_empty());

debug!("Scopes: {:?}", scopes);

ROScopes(scopes)
}
}

impl<'viewee> From<&'viewee ROScope<'viewee>> for &'viewee str {
/// Get the underlying string slice.
///
/// All variants contain such a slice, so this is a convenient method.
fn from(s: &'viewee ROScope) -> Self {
match s.0 {
Scope::In(s) | Scope::Out(s) => s,
}
}
}

impl<'viewee> From<ROScope<'viewee>> for RWScope<'viewee> {
fn from(s: ROScope<'viewee>) -> Self {
match s.0 {
Scope::In(s) => RWScope(Scope::In(Cow::Borrowed(s))),
Scope::Out(s) => RWScope(Scope::Out(s)),
}
}
}

impl<'viewee> From<&'viewee RWScope<'viewee>> for &'viewee str {
/// Get the underlying string slice.
///
/// All variants contain such a slice, so this is a convenient method.
fn from(s: &'viewee RWScope) -> Self {
match &s.0 {
Scope::In(s) => s,
Scope::Out(s) => s,
}
}
}

0 comments on commit e951347

Please sign in to comment.