Skip to content

Commit

Permalink
Allow reverse nested search
Browse files Browse the repository at this point in the history
  • Loading branch information
DmitryAstafyev committed Jan 9, 2025
1 parent f9afaed commit 12d90d3
Show file tree
Hide file tree
Showing 12 changed files with 87 additions and 35 deletions.
10 changes: 10 additions & 0 deletions application/apps/indexer/processor/src/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,16 @@ impl SearchMap {
Ok(&self.matches[from as usize..])
}

pub fn indexes_to_rev(&self, to: u64) -> Result<&[stypes::FilterMatch], MapError> {
if to >= self.len() as u64 {
return Err(MapError::OutOfRange(format!(
"Search has: {} matches. Requested from: {to}",
self.len(),
)));
}
Ok(&self.matches[..to as usize])
}

pub fn get_match_index(&self, pos: u64) -> Option<u64> {
self.matches.iter().enumerate().find_map(|(index, m)| {
if m.index == pos {
Expand Down
3 changes: 2 additions & 1 deletion application/apps/indexer/session/src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,10 @@ impl Session {
&self,
filter: SearchFilter,
from: u64,
rev: bool,
) -> Result<Option<(u64, u64)>, stypes::ComputationError> {
self.state
.search_nested_match(filter, from)
.search_nested_match(filter, from, rev)
.await
.map_err(stypes::ComputationError::NativeError)
}
Expand Down
5 changes: 4 additions & 1 deletion application/apps/indexer/session/src/state/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,12 @@ pub enum Api {
oneshot::Sender<Result<Vec<GrabbedElement>, stypes::NativeError>>,
),
),
#[allow(clippy::type_complexity)]
SearchNestedMatch(
(
SearchFilter,
u64,
bool,
oneshot::Sender<Result<Option<(u64, u64)>, stypes::NativeError>>,
),
),
Expand Down Expand Up @@ -376,9 +378,10 @@ impl SessionStateAPI {
&self,
filter: SearchFilter,
from: u64,
rev: bool,
) -> Result<Option<(u64, u64)>, stypes::NativeError> {
let (tx, rx) = oneshot::channel();
self.exec_operation(Api::SearchNestedMatch((filter, from, tx)), rx)
self.exec_operation(Api::SearchNestedMatch((filter, from, rev, tx)), rx)
.await?
}

Expand Down
47 changes: 30 additions & 17 deletions application/apps/indexer/session/src/state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,27 +152,40 @@ impl SessionState {
&mut self,
filter: SearchFilter,
from: u64,
rev: bool,
) -> Result<Option<(u64, u64)>, stypes::NativeError> {
let indexes = self
.search_map
.indexes_from(from)
.map_err(|e| stypes::NativeError {
severity: stypes::Severity::ERROR,
kind: stypes::NativeErrorKind::Grabber,
message: Some(format!("{e}")),
})?;
let indexes = if !rev {
self.search_map.indexes_from(from)
} else {
self.search_map.indexes_to_rev(from)
}
.map_err(|e| stypes::NativeError {
severity: stypes::Severity::ERROR,
kind: stypes::NativeErrorKind::Grabber,
message: Some(format!("{e}")),
})?;
let searcher = LineSearcher::new(&filter).map_err(|e| stypes::NativeError {
severity: stypes::Severity::ERROR,
kind: stypes::NativeErrorKind::OperationSearch,
message: Some(e.to_string()),
})?;
for range in self.transform_indexes(indexes).iter() {
if let Some(ln) = self
.session_file
.grab(&LineRange::from(range.clone()))?
.iter()
.find(|ln| searcher.is_match(&ln.content))
{
let mut indexes: std::vec::IntoIter<RangeInclusive<u64>> =
self.transform_indexes(indexes).into_iter();
while let Some(range) = if !rev {
indexes.next()
} else {
indexes.next_back()
} {
let grabbed = self.session_file.grab(&LineRange::from(range.clone()))?;
let found = if !rev {
grabbed.iter().find(|ln| searcher.is_match(&ln.content))
} else {
grabbed
.iter()
.rev()
.find(|ln| searcher.is_match(&ln.content))
};
if let Some(ln) = found {
let Some(srch_pos) = self.search_map.get_match_index(ln.pos as u64) else {
return Err(stypes::NativeError {
severity: stypes::Severity::ERROR,
Expand Down Expand Up @@ -657,9 +670,9 @@ pub async fn run(
stypes::NativeError::channel("Failed to respond to Api::GrabSearch")
})?;
}
Api::SearchNestedMatch((filter, from, tx_response)) => {
Api::SearchNestedMatch((filter, from, rev, tx_response)) => {
tx_response
.send(state.handle_search_nested_match(filter, from))
.send(state.handle_search_nested_match(filter, from, rev))
.map_err(|_| {
stypes::NativeError::channel("Failed to respond to Api::SearchNestedMatch")
})?;
Expand Down
2 changes: 2 additions & 0 deletions application/apps/rustcore/rs-bindings/src/js/session/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,7 @@ impl RustSession {
&self,
filter: WrappedSearchFilter,
from: i64,
rev: bool,
) -> Result<Option<(i64, i64)>, stypes::ComputationError> {
let res = self
.session
Expand All @@ -399,6 +400,7 @@ impl RustSession {
.search_nested_match(
filter.as_filter(),
u64::try_from(from).map_err(|_| stypes::ComputationError::InvalidData)?,
rev,
)
.await?;
Ok(if let Some((pos, srch_pos)) = res {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,12 @@ export class SessionSearch {
return this.managers.search.run(filters);
}

public searchNestedMatch(filter: IFilter, from: number): Promise<[number, number] | undefined> {
return this.session.searchNestedMatch(filter, from);
public searchNestedMatch(
filter: IFilter,
from: number,
rev: boolean,
): Promise<[number, number] | undefined> {
return this.session.searchNestedMatch(filter, from, rev);
}

public values(filters: string[]): ICancelablePromise<void> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ export abstract class RustSession extends RustSessionRequiered {
public abstract searchNestedMatch(
filter: IFilter,
from: number,
rev: boolean,
): Promise<[number, number] | undefined>;

public abstract search(filters: IFilter[], operationUuid: string): Promise<void>;
Expand Down Expand Up @@ -295,6 +296,7 @@ export abstract class RustSessionNative {
is_word: boolean;
},
from: number,
rev: boolean,
): Promise<[number, number] | undefined>;

public abstract applySearchValuesFilters(
Expand Down Expand Up @@ -841,7 +843,11 @@ export class RustSessionWrapper extends RustSession {
});
}

public searchNestedMatch(filter: IFilter, from: number): Promise<[number, number] | undefined> {
public searchNestedMatch(
filter: IFilter,
from: number,
rev: boolean,
): Promise<[number, number] | undefined> {
return new Promise((resolve, reject) => {
try {
this._native
Expand All @@ -853,6 +859,7 @@ export class RustSessionWrapper extends RustSession {
is_word: filter.flags.word,
},
from,
rev,
)
.then(resolve)
.catch((err: Error) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ export class Search extends Subscriber {
});
}

public searchNestedMatch(): Promise<[number, number] | undefined> {
public searchNestedMatch(rev: boolean): Promise<[number, number] | undefined> {
const filter = this.state().nested().get();
if (filter === undefined) {
return Promise.resolve(undefined);
Expand All @@ -121,7 +121,8 @@ export class Search extends Subscriber {
new Requests.Search.NextNested.Request({
session: this._uuid,
filter,
from: this.state().nested().nextPos(),
from: rev ? this.state().nested().prevPos() : this.state().nested().nextPos(),
rev,
}),
)
.then((response) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { Search } from '@service/session/dependencies/search';
import { unique } from '@platform/env/sequence';

import * as obj from '@platform/env/obj';
import { FilterRequest } from './filters/request';

export interface ISearchFinishEvent {
found: number;
Expand Down Expand Up @@ -119,18 +118,21 @@ export class State {
}

public nested(): {
accept(action: Promise<[number, number] | undefined>): Promise<number | undefined>;
next(): Promise<number | undefined>;
prev(): Promise<number | undefined>;
set(filter: IFilter): Promise<number | undefined>;
nextPos(): number;
prevPos(): number;
get(): IFilter | undefined;
drop(): void;
} {
return {
next: (): Promise<number | undefined> => {
accept: (
action: Promise<[number, number] | undefined>,
): Promise<number | undefined> => {
return new Promise((resolve, reject) => {
this._controller
.searchNestedMatch()
action
.then((pos: [number, number] | undefined) => {
if (pos === undefined) {
this._nested.from = -1;
Expand All @@ -148,8 +150,11 @@ export class State {
});
});
},
next: (): Promise<number | undefined> => {
return this.nested().accept(this._controller.searchNestedMatch(false));
},
prev: (): Promise<number | undefined> => {
return Promise.resolve(0);
return this.nested().accept(this._controller.searchNestedMatch(true));
},
set: (filter: IFilter): Promise<number | undefined> => {
this._nested.filter = obj.clone(filter);
Expand All @@ -163,6 +168,13 @@ export class State {
return this._nested.from + 1;
}
},
prevPos: (): number => {
if (this._nested.from <= 0) {
return this._controller.len() - 1;
} else {
return this._nested.from - 1;
}
},
get: (): IFilter | undefined => {
return this._nested.filter;
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ import { Ilc, IlcInterface } from '@env/decorators/component';
import { SearchInput } from '../input/input';
import { List } from '@env/storages/recent/list';
import { ChangesDetector } from '@ui/env/extentions/changes';
import { ISearchFinishEvent } from '@service/session/dependencies/search/state';
import { Notification } from '@ui/service/notifications';
import { IFilter } from '@platform/types/filter';
import { Owner } from '@schema/content/row';

@Component({
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { CancelablePromise } from 'platform/env/promise';
import { sessions, Jobs } from '@service/sessions';
import { sessions } from '@service/sessions';
import { Logger } from 'platform/log';
import { ICancelablePromise } from 'platform/env/promise';

Expand All @@ -24,7 +24,7 @@ export const handler = Requests.InjectLogger<
}
stored.session
.getSearch()
.searchNestedMatch(request.filter, request.from)
.searchNestedMatch(request.filter, request.from, request.rev)
.then((pos: [number, number] | undefined) => {
resolve(
new Requests.Search.NextNested.Response({
Expand Down
4 changes: 3 additions & 1 deletion application/platform/ipc/request/search/next_nested.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,15 @@ export class Request extends SignatureRequirement {
public session: string;
public filter: IFilter;
public from: number;
public rev: boolean;

constructor(input: { session: string; filter: IFilter; from: number }) {
constructor(input: { session: string; filter: IFilter; from: number; rev: boolean }) {
super();
validator.isObject(input);
this.session = validator.getAsNotEmptyString(input, 'session');
this.filter = validator.getAsObj(input, 'filter');
this.from = validator.getAsValidNumber(input, 'from');
this.rev = validator.getAsBool(input, 'rev');
}
}

Expand Down

0 comments on commit 12d90d3

Please sign in to comment.