-
Notifications
You must be signed in to change notification settings - Fork 21
Description
TL;DR
Float Elements need some special handling:
- If the Element Size is 0 ("empty float"), interpret as default value (or 0.0, if no default)
- some NaN stuff (low priority, probably not an issue in practice)
Read on for (a lot) more detail
Summary of the spec
The EBML Float Element consists of an Element ID, an Element Size and the Element Data (like most Elements). The Element ID and Element Size are VINTs.
The EBML spec says that the size can be 0, 4, or 8. A size of 4 or 8 means that the data is a big-endian 32- or 64-bit floating-point number as defined in IEEE 754. A size of 0 (what I might call an "empty float") is equivalent to the default value of that Element, or 0.0 if the Element has no default. Any other Element Size is not allowed.
Like most Elements, Float Elements are optional if
- minOccurs is 0 (or not specified) OR
- minOccurs = maxOccurs = 1 AND the Element has a default value in the spec.
Otherwise, they are required.
NaN
The Rust docs for f32 have a small explanation of the issues with signalling and quiet NaN handling:
However there is one caveat: prior to the 2008 version of IEEE 754, how to interpret the NaN signaling bit wasn’t actually specified. Most platforms (notably x86 and ARM) picked the interpretation that was ultimately standardized in 2008, but some didn’t (notably MIPS). As a result, all signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa.
I wasn't aware of this and thought it was still not specified. Now it might make sense to test IEEE 754-2008 compliance, but it's probably not required. I'm not sure NaNs (and more specifically, correct NaN handling in terms of quiet and signalling NaNs) will ever be an issue for Matroska.
Error & edge case handling
(originally addressed in #115)
When parsing a Float Element, there's 3 relevant edge cases we should maybe handle:
- A nom
VerifyError-> Float Element with that ID doesn't exist - A
ParseError::EmptyFloat-> Element exists but has a length of 0. - A
ParseError::FloatWidthIncorrect-> Element exists but has a length that is not 0, 4 or 8.
The type we use on the Rust side is either an Option<f64> (optional, if minOccurs = 0) or an f64 (required, if minOccurs = maxOccurs = 1).
I think we want this behaviour:
| No. | Output type | VerifyError | EmptyFloat |
|---|---|---|---|
| 1 | Option<f64> |
None |
Some(0) |
| 2 | f64, no default |
Err |
0 |
| 3 | f64, default d |
d |
d |