Skip to content

Commit

Permalink
Use : instead of . as the entity:component separator in paths (#4471
Browse files Browse the repository at this point in the history
)

### What
* Part of #4338

This is a very minor breaking change, where existing links in markdown
to specific _components_ of an entity will break.

Before: `recording://helix/structure.Transform3D`
After: `recording://helix/structure:Transform3D`

The purpose is to allow `.` as a valid character in a path part, e.g. as
`images/foo.jpg`
  • Loading branch information
emilk committed Dec 12, 2023
1 parent bf2ef19 commit 7358cb1
Show file tree
Hide file tree
Showing 11 changed files with 44 additions and 44 deletions.
1 change: 1 addition & 0 deletions crates/re_data_ui/src/item_ui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ pub fn component_path_button(
component_path.component_name.short_name(),
component_path,
)
.on_hover_text(component_path.component_name.full_name()) // we should show the full name somewhere
}

/// Show a component path and make it selectable.
Expand Down
6 changes: 3 additions & 3 deletions crates/re_log_types/src/path/data_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ use crate::EntityPath;
/// For instance:
///
/// * `points`
/// * `points.Color`
/// * `points:Color`
/// * `points[#42]`
/// * `points[#42].Color`
/// * `points[#42]:Color`
#[derive(Clone, Eq, PartialEq, Hash)]
pub struct DataPath {
pub entity_path: EntityPath,
Expand All @@ -29,7 +29,7 @@ impl std::fmt::Display for DataPath {
write!(f, "[#{}]", instance_key.0)?;
}
if let Some(component_name) = &self.component_name {
write!(f, ".{component_name:?}")?;
write!(f, ":{component_name:?}")?;
}
Ok(())
}
Expand Down
53 changes: 26 additions & 27 deletions crates/re_log_types/src/path/parse_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ pub enum PathParseError {
#[error("Found no component name")]
MissingComponentName,

#[error("Found trailing dot (.)")]
TrailingDot,
#[error("Found trailing colon (:)")]
TrailingColon,
}

type Result<T, E = PathParseError> = std::result::Result<T, E>;
Expand All @@ -63,9 +63,9 @@ impl std::str::FromStr for DataPath {
/// For instance:
///
/// * `world/points`
/// * `world/points.Color`
/// * `world/points:Color`
/// * `world/points[#42]`
/// * `world/points[#42].rerun.components.Color`
/// * `world/points[#42]:rerun.components.Color`
fn from_str(path: &str) -> Result<Self, Self::Err> {
if path.is_empty() {
return Err(PathParseError::EmptyString);
Expand All @@ -78,21 +78,20 @@ impl std::str::FromStr for DataPath {
let mut component_name = None;
let mut instance_key = None;

// Parse `.rerun.components.Color` suffix:
if let Some(dot) = tokens.iter().position(|&token| token == ".") {
let component_tokens = &tokens[dot + 1..];
// Parse `:rerun.components.Color` suffix:
if let Some(colon) = tokens.iter().position(|&token| token == ":") {
let component_tokens = &tokens[colon + 1..];

if component_tokens.is_empty() {
return Err(PathParseError::TrailingDot);
} else if component_tokens.len() == 1 {
component_name = Some(ComponentName::from(format!(
"rerun.components.{}",
join(component_tokens)
)));
return Err(PathParseError::TrailingColon);
} else {
component_name = Some(ComponentName::from(join(component_tokens)));
let mut name = join(component_tokens);
if !name.contains('.') {
name = format!("rerun.components.{name}");
}
component_name = Some(ComponentName::from(name));
}
tokens.truncate(dot);
tokens.truncate(colon);
}

// Parse `[#1234]` suffix:
Expand Down Expand Up @@ -331,12 +330,12 @@ fn join(tokens: &[&str]) -> String {

fn tokenize(path: &str) -> Result<Vec<&str>> {
#![allow(clippy::unwrap_used)]
// We parse on bytes, and take care to only split on either side of a one-byte ASCI,
// making the `from_utf8(…)s below.u
// We parse on bytes, and take care to only split on either side of a one-byte ASCII,
// making the `from_utf8(…)`s below safe to unwrap.
let mut bytes = path.as_bytes();

fn is_special_character(c: u8) -> bool {
matches!(c, b'[' | b']' | b'.' | b'/')
matches!(c, b'[' | b']' | b':' | b'/')
}

let mut tokens = vec![];
Expand Down Expand Up @@ -533,7 +532,7 @@ fn test_parse_entity_path_strict() {

assert_eq!(parse("foo/bar/"), Err(PathParseError::TrailingSlash));
assert!(matches!(
parse(r#"entity.component"#),
parse(r#"entity:component"#),
Err(PathParseError::UnexpectedComponentName { .. })
));
assert!(matches!(
Expand All @@ -545,52 +544,52 @@ fn test_parse_entity_path_strict() {
#[test]
fn test_parse_component_path() {
assert_eq!(
ComponentPath::from_str("world/points.rerun.components.Color"),
ComponentPath::from_str("world/points:rerun.components.Color"),
Ok(ComponentPath {
entity_path: EntityPath::from("world/points"),
component_name: "rerun.components.Color".into(),
})
);
assert_eq!(
ComponentPath::from_str("world/points.Color"),
ComponentPath::from_str("world/points:Color"),
Ok(ComponentPath {
entity_path: EntityPath::from("world/points"),
component_name: "rerun.components.Color".into(),
})
);
assert_eq!(
ComponentPath::from_str("world/points.my.custom.color"),
ComponentPath::from_str("world/points:my.custom.color"),
Ok(ComponentPath {
entity_path: EntityPath::from("world/points"),
component_name: "my.custom.color".into(),
})
);
assert_eq!(
ComponentPath::from_str("world/points."),
Err(PathParseError::TrailingDot)
ComponentPath::from_str("world/points:"),
Err(PathParseError::TrailingColon)
);
assert_eq!(
ComponentPath::from_str("world/points"),
Err(PathParseError::MissingComponentName)
);
assert_eq!(
ComponentPath::from_str("world/points[#42].rerun.components.Color"),
ComponentPath::from_str("world/points[#42]:rerun.components.Color"),
Err(PathParseError::UnexpectedInstanceKey(InstanceKey(42)))
);
}

#[test]
fn test_parse_data_path() {
assert_eq!(
DataPath::from_str("world/points[#42].rerun.components.Color"),
DataPath::from_str("world/points[#42]:rerun.components.Color"),
Ok(DataPath {
entity_path: EntityPath::from("world/points"),
instance_key: Some(InstanceKey(42)),
component_name: Some("rerun.components.Color".into()),
})
);
assert_eq!(
DataPath::from_str("world/points.rerun.components.Color"),
DataPath::from_str("world/points:rerun.components.Color"),
Ok(DataPath {
entity_path: EntityPath::from("world/points"),
instance_key: None,
Expand Down
4 changes: 2 additions & 2 deletions crates/re_types/src/archetypes/text_document.rs

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

4 changes: 2 additions & 2 deletions docs/code-examples/text_document.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ int main() {
rec.log(
"markdown",
rerun::TextDocument(R"#(# Hello Markdown!
[Click here to see the raw text](recording://markdown.Text).
[Click here to see the raw text](recording://markdown:Text).
Basic formatting:
Expand All @@ -37,7 +37,7 @@ Basic formatting:
## Links
You can link to [an entity](recording://markdown),
a [specific instance of an entity](recording://markdown[#0]),
or a [specific component](recording://markdown.Text).
or a [specific component](recording://markdown:Text).
Of course you can also have [normal https links](https://github.com/rerun-io/rerun), e.g. <https://rerun.io>.
Expand Down
4 changes: 2 additions & 2 deletions docs/code-examples/text_document.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
rr.TextDocument(
'''
# Hello Markdown!
[Click here to see the raw text](recording://markdown.Text).
[Click here to see the raw text](recording://markdown:Text).
Basic formatting:
Expand All @@ -37,7 +37,7 @@
## Links
You can link to [an entity](recording://markdown),
a [specific instance of an entity](recording://markdown[#0]),
or a [specific component](recording://markdown.Text).
or a [specific component](recording://markdown:Text).
Of course you can also have [normal https links](https://github.com/rerun-io/rerun), e.g. <https://rerun.io>.
Expand Down
4 changes: 2 additions & 2 deletions docs/code-examples/text_document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
&rerun::TextDocument::new(
r#"
# Hello Markdown!
[Click here to see the raw text](recording://markdown.Text).
[Click here to see the raw text](recording://markdown:Text).
Basic formatting:
Expand All @@ -39,7 +39,7 @@ Basic formatting:
## Links
You can link to [an entity](recording://markdown),
a [specific instance of an entity](recording://markdown[#0]),
or a [specific component](recording://markdown.Text).
or a [specific component](recording://markdown:Text).
Of course you can also have [normal https links](https://github.com/rerun-io/rerun), e.g. <https://rerun.io>.
Expand Down
2 changes: 1 addition & 1 deletion examples/python/dna/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
### Rotation
The whole structure is rotated over time by logging a
[rr.Transform3D archetype](https://www.rerun.io/docs/reference/types/archetypes/transform3d) to the
[helix/structure entity](recording://helix/structure.Transform3D) that changes over time. This transform determines the rotation of
[helix/structure entity](recording://helix/structure:Transform3D) that changes over time. This transform determines the rotation of
the [structure entity](recording://helix/structure) relative to the [helix](recording://helix) entity. Since all other
entities are children of [helix/structure](recording://helix/structure) they will also rotate based on this transform.
Expand Down
2 changes: 1 addition & 1 deletion examples/python/structure_from_motion/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
```python
rr.log("points", rr.Points3D(points, colors=point_colors), rr.AnyValues(error=point_errors))
```
**Note:** we added some [custom per-point errors](recording://points.error) that you can see when you
**Note:** we added some [custom per-point errors](recording://points) that you can see when you
hover over the points in the 3D view.
""".strip()

Expand Down
4 changes: 2 additions & 2 deletions rerun_cpp/src/rerun/archetypes/text_document.hpp

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

4 changes: 2 additions & 2 deletions rerun_py/rerun_sdk/rerun/archetypes/text_document.py

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

0 comments on commit 7358cb1

Please sign in to comment.