Skip to content

Commit

Permalink
Convert the SpaceViewArchetype to use QueryExpression as a batch (rer…
Browse files Browse the repository at this point in the history
…un-io#5516)

### What
Working with lists of query expressions is generally much more ergonomic
than wrangling newline separated strings in the blueprint APIs.

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/5516/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/5516/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/5516/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG
* [x] If applicable, add a new check to the [release
checklist](https://github.com/rerun-io/rerun/blob/main/tests/python/release_checklist)!

- [PR Build Summary](https://build.rerun.io/pr/5516)
- [Docs
preview](https://rerun.io/preview/8adae8bec4acb3de40258d08819073ec5e6b82fa/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/8adae8bec4acb3de40258d08819073ec5e6b82fa/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)
  • Loading branch information
jleibs authored Mar 15, 2024
1 parent c8d6edf commit 458862b
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 162 deletions.
34 changes: 24 additions & 10 deletions crates/re_log_types/src/path/entity_path_filter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::collections::BTreeMap;

use itertools::Itertools as _;

use crate::EntityPath;

/// A way to filter a set of `EntityPath`s.
Expand Down Expand Up @@ -101,10 +103,22 @@ impl EntityPathFilter {
///
/// Conflicting rules are resolved by the last rule.
pub fn parse_forgiving(rules: &str) -> Self {
Self::from_query_expressions(rules.split('\n'))
}

/// Build a filter from a list of query expressions.
///
/// Each item in the iterator should be a query expression.
///
/// The first character should be `+` or `-`. If missing, `+` is assumed.
/// The rest of the expression is trimmed and treated as an entity path.
///
/// Conflicting rules are resolved by the last rule.
pub fn from_query_expressions<'a>(rules: impl IntoIterator<Item = &'a str>) -> Self {
let mut filter = Self::default();

for line in rules
.split('\n')
.into_iter()
.map(|line| line.trim())
.filter(|line| !line.is_empty())
{
Expand Down Expand Up @@ -140,9 +154,9 @@ impl EntityPathFilter {
self.rules.insert(rule, effect);
}

pub fn formatted(&self) -> String {
let mut s = String::new();
for (rule, effect) in &self.rules {
pub fn iter_expressions(&self) -> impl Iterator<Item = String> + '_ {
self.rules.iter().map(|(rule, effect)| {
let mut s = String::new();
s.push_str(match effect {
RuleEffect::Include => "+ ",
RuleEffect::Exclude => "- ",
Expand All @@ -156,12 +170,12 @@ impl EntityPathFilter {
s.push_str("/**");
}
}
s.push('\n');
}
if s.ends_with('\n') {
s.pop();
}
s
s
})
}

pub fn formatted(&self) -> String {
self.iter_expressions().join("\n")
}

/// Find the most specific matching rule and return its effect.
Expand Down
13 changes: 10 additions & 3 deletions crates/re_space_view/src/space_view_contents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,9 @@ impl SpaceViewContents {
Default::default()
});

let entity_path_filter = EntityPathFilter::parse_forgiving(query.0.as_str());
let query = query.iter().map(|qe| qe.0.as_str());

let entity_path_filter = EntityPathFilter::from_query_expressions(query);

Self {
blueprint_entity_path,
Expand All @@ -130,7 +132,9 @@ impl SpaceViewContents {
pub fn save_to_blueprint_store(&self, ctx: &ViewerContext<'_>) {
ctx.save_blueprint_archetype(
self.blueprint_entity_path.clone(),
&blueprint_archetypes::SpaceViewContents::new(self.entity_path_filter.formatted()),
&blueprint_archetypes::SpaceViewContents::new(
self.entity_path_filter.iter_expressions(),
),
);
}

Expand All @@ -145,7 +149,10 @@ impl SpaceViewContents {

ctx.save_blueprint_component(
&self.blueprint_entity_path,
&QueryExpression(new_entity_path_filter.formatted().into()),
&new_entity_path_filter
.iter_expressions()
.map(|s| QueryExpression(s.into()))
.collect::<Vec<_>>(),
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,48 @@ namespace rerun.blueprint.archetypes;
// ---

/// The contents of a `SpaceView`.
///
/// The contents are found by combining a collection of `QueryExpression`s.
///
/// ```diff
/// + /world/** # add everything…
/// - /world/roads/** # …but remove all roads…
/// + /world/roads/main # …but show main road
/// ```
///
/// If there is multiple matching rules, the most specific rule wins.
/// If there are multiple rules of the same specificity, the last one wins.
/// If no rules match, the path is excluded.
///
/// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively
/// (`/world/**` matches both `/world` and `/world/car/driver`).
/// Other uses of `*` are not (yet) supported.
///
/// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive.
/// This means the last matching rule is also the most specific one. For instance:
/// ```diff
/// + /world/**
/// - /world
/// - /world/car/**
/// + /world/car/driver
/// ```
///
/// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included.
/// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded.
/// The last rule matching `/world` is `- /world`, so it is excluded.
/// The last rule matching `/world/house` is `+ /world/**`, so it is included.
///
/// Unstable. Used for the ongoing blueprint experimentations.
table SpaceViewContents (
"attr.rerun.scope": "blueprint",
"attr.rust.derive": "Default"
) {
// --- Required ---

// --- Optional ---

/// The `QueryExpression` that populates the contents for the `SpaceView`.
///
/// They determine which entities are part of the spaceview.
query: rerun.blueprint.components.QueryExpression ("attr.rerun.component_required", order: 1000);
query: [rerun.blueprint.components.QueryExpression] ("attr.rerun.component_optional", order: 1000);
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,40 +8,17 @@ include "rerun/attributes.fbs";
namespace rerun.blueprint.components;

// ---
/// A way to filter a set of `EntityPath`s.
/// An individual `QueryExpression` used to filter a set of `EntityPath`s.
///
/// This implements as simple set of include/exclude rules:
/// Each expression is either an inclusion or an exclusion expression.
/// Inclusions start with an optional `+` and exclusions must start with a `-`.
///
/// ```diff
/// + /world/** # add everything…
/// - /world/roads/** # …but remove all roads…
/// + /world/roads/main # …but show main road
/// ```
///
/// If there is multiple matching rules, the most specific rule wins.
/// If there are multiple rules of the same specificity, the last one wins.
/// If no rules match, the path is excluded.
/// Multiple expressions are combined together as part of `SpaceViewContents`.
///
/// The `/**` suffix matches the whole subtree, i.e. self and any child, recursively
/// (`/world/**` matches both `/world` and `/world/car/driver`).
/// Other uses of `*` are not (yet) supported.
///
/// Internally, `EntityPathFilter` sorts the rule by entity path, with recursive coming before non-recursive.
/// This means the last matching rule is also the most specific one.
/// For instance:
///
/// ```diff
/// + /world/**
/// - /world
/// - /world/car/**
/// + /world/car/driver
/// ```
///
/// The last rule matching `/world/car/driver` is `+ /world/car/driver`, so it is included.
/// The last rule matching `/world/car/hood` is `- /world/car/**`, so it is excluded.
/// The last rule matching `/world` is `- /world`, so it is excluded.
/// The last rule matching `/world/house` is `+ /world/**`, so it is included.
///
/// Unstable. Used for the ongoing blueprint experimentations.
table QueryExpression (
"attr.rerun.scope": "blueprint",
Expand Down
64 changes: 51 additions & 13 deletions crates/re_types/src/blueprint/archetypes/space_view_contents.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 4 additions & 27 deletions crates/re_types/src/blueprint/components/query_expression.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 458862b

Please sign in to comment.