niftools / nifxml

A repository for the nif.xml file, which contains the nif file format description.
http://www.niftools.org
GNU General Public License v3.0
37 stars 43 forks source link

[Spec] Block contracts #55

Open hexabits opened 8 years ago

hexabits commented 8 years ago

A contract is a formal set of obligations which a data structure must follow. Generally it is a precondition, a postcondition, or an invariant (an assertion which must stay true). You can read up on it here.

For our uses a contract would be something that must be true for a block, evaluated at parse time. Contracts can provide additional details about a block that otherwise wouldn't be defined (i.e. it's a form of documentation) and can be used for validation as well as performance optimizations.

Reasoning

For Fallout 4, a vertex is now a compound with 15 conditional rows. NifSkope evaluates the conditions per row for each vertex which is unnecessary because the conditions are passed down from the BSTriShape, thus every row will have the same conditions on each vertex. So, to parse this compound at any reasonable speed I inserted an attribute on my shipped nif.xml which tells NifSkope the cond are all external (i.e. ARG) and to optimize this compound.

With a contract on the BSVertexData compound I was able to cache the conditions for subsequent vertices and speed up reading by over 12x.

Suggested Contracts

External Conditions externalcond

Potential Contracts

No Conditions nocond

No Version Conditions novercond

Fixed Size fixed

Basic basic

Implicit Contracts

Some contracts would be implicit for a block type and not need to be defined.

There is not much use for explicitly defining internalcond or mixedcond for anything.

Proposed Syntax

Single contract

<compound name="BSVertexData" implements="externalcond">

Multiple contracts

<!-- Correct way to make lists in XML attributes is space-separated -->
<compound name="BSVertexData" implements="externalcond novercond">

Parsing

Implemented as a new attribute in this way, the XML would still be backwards compatible. In fact different parsers would never have to support this at all if they did not want to. But when it comes to authoring the XML, one would still have to write valid contracts and check on parsers who do use them.

As for error checking, each contract need only be concerned with its own rules, and interactions between contracts shall not be a concern. Take for example externalcond + nocond.

Up for discussion

neomonkeus commented 8 years ago

Do we this for only compounds or do we also do it for niobjects?

How we document the contracts at the top of the file.. Do they get their own XML tag like ? Or just a comment block?

Which of the "potential" contracts do we really need? Are there any contracts you could think of that would be useful for documenting or validating the data behaviour?

Is the syntax sufficient, or would anyone care to propose alternatives? If the syntax is fine, I will submit a PR for externalcond usage ASAP, as it's needed to merge nifskope dev/2.0 to develop.