Skip to content

Define, implement & test handling of Float Elements #116

@FreezyLemon

Description

@FreezyLemon

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:

  1. A nom VerifyError -> Float Element with that ID doesn't exist
  2. A ParseError::EmptyFloat -> Element exists but has a length of 0.
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    spec-complianceRelated to EBML or Matroska specification compliance

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions