Skip to content

Commit

Permalink
fix: as_las_string_lossy ignores anything after the first null charac…
Browse files Browse the repository at this point in the history
…ter (#100)

I just came across a las file with the following Extra-Attributes VLR: 

```
Vlr {
    user_id: "LASF_Spec\0\0\0\0\0\u{18}\0",
    record_id: 4,
    ...
}
```

The user_id is not properly filled with null characters (see the
`\u{18}` hidden in there...). In this case, `as_las_string_lossy`
currently returns the full string including all null characters. This
results in the extra-bytes VLR not being detected correctly in my own
code. Most other tools like LasTools or CloudCompare seem to have no
problem with this and just ignore anything after the first null
character. I changed `as_las_string_lossy` to work this way, too. Now
`as_las_string_lossy` correctly parses above user id as "LASF_Spec".

Co-authored-by: Tobias Dorra <[email protected]>
  • Loading branch information
tobias93 and Tobias Dorra authored Dec 17, 2024
1 parent a2c410f commit 3871af9
Show file tree
Hide file tree
Showing 2 changed files with 15 additions and 12 deletions.
11 changes: 10 additions & 1 deletion src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,10 @@ impl AsLasStr for &'_ [u8] {
fn as_las_string_lossy(&self) -> String {
match self.as_las_str() {
Ok(s) => s.to_string(),
Err(_) => String::from_utf8_lossy(self).to_string(),
Err(_) => {
let len = self.iter().position(|c| *c == 0).unwrap_or(self.len());
String::from_utf8_lossy(&self[..len]).to_string()
}
}
}
}
Expand Down Expand Up @@ -101,4 +104,10 @@ mod tests {
let mut bytes = [0; 5];
assert!(bytes.as_mut().from_las_str("Beer!!").is_err());
}

#[test]
fn lossy_from_not_null_filled() {
let bytes = [65, 66, 67, 0, 68];
assert_eq!("ABC", bytes.as_ref().as_las_string_lossy());
}
}
16 changes: 5 additions & 11 deletions src/vlr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -191,29 +191,23 @@ mod tests {
#[test]
fn allow_non_ascii_user_id() {
let raw_vlr = raw::Vlr {
user_id: [0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
user_id: [194, 174, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0],
..Default::default()
};
let vlr = Vlr::new(raw_vlr);
assert_eq!(
"\u{0}*\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}",
vlr.user_id
);
assert_eq!("®", vlr.user_id);
}

#[test]
fn allow_non_ascii_description() {
let raw_vlr = raw::Vlr {
description: [
0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0,
194, 174, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
],
..Default::default()
};
let vlr = Vlr::new(raw_vlr);
assert_eq!(
"\u{0}*\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}*\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}",
vlr.description
);
assert_eq!("®", vlr.description);
}
}

0 comments on commit 3871af9

Please sign in to comment.