Consistently handling user types and built-in sized types
# Summary
Trying to formalize the way how size-related properties should model a Kaitai Struct type, I found some inconsistences. In the spoilers below you can see a diagrams that shown how each part of a binary stream is used by an attribute depending on which how that attribute is defined:

<details><summary>`size-eos: true`</summary>

The size of an attribute is defined by a `size-eos: true` key:
* ```yaml
  #          /==\ - type
  # Stream: [____                            ]
  #         0                                eos
  #          \_______available for type_____/
  #           \_______consumed bytes_______/
  #            \_____________stream size__/
  size-eos: true
  ```
* ```yaml
  #          /==\ - type
  # Stream: [____                  x         ]
  #         0                  terminator    eos
  #          \_available for type_/         /
  #           \_______consumed bytes_______/
  #            \_____________stream size__/
  size-eos: true
  terminator: x
  ```
* ```yaml
  #          /==\ - type           /========\ - padding
  # Stream: [____                  ~~~~~~~~~~]
  #         0                                eos
  #          \_available for type_/         /
  #           \_______consumed bytes_______/
  #            \_____________stream size__/
  size-eos: true
  pad-right: ~
  # terminator: ~ - implicit
  ```
* ```yaml
  #          /==\ - type            /=======\ - padding
  # Stream: [____                  x~~~~~~~~~]
  #         0                                eos
  #          \_available for type_/         /
  #           \_______consumed bytes_______/
  #            \_____________stream size__/
  size-eos: true
  terminator: x
  pad-right: ~
  ```
</details>
<details><summary>`size`</summary>

The size of an attribute is defined by a `size` key:
* ```yaml
  #          /==\ - type
  # Stream: [____                       ]    |
  #         0                                eos
  #          \____available for type___/    /
  #           \_____consumed bytes____/    /
  #            \_____________stream size__/
  size: s
  ```
* ```yaml
  #          /==\ - type
  # Stream: [____                  x    ]    |
  #         0                  terminator    eos
  #          \_available for type_/    /    /
  #           \_____consumed bytes____/    /
  #            \_____________stream size__/
  size: s
  terminator: x
  ```
* ```yaml
  #          /==\ - type           /===\ - padding
  # Stream: [____                  ~~~~~]    |
  #         0                                eos
  #          \_available for type_/    /    /
  #           \_____consumed bytes____/    /
  #            \_____________stream size__/
  size: s
  pad-right: ~
  # terminator: ~ - implicit
  ```
* ```yaml
  #          /==\ - type            /==\ - padding
  # Stream: [____                  x~~~~]    |
  #         0                  terminator    eos
  #          \_available for type_/    /    /
  #           \_____consumed bytes____/    /
  #            \_____________stream size__/
  size: s
  terminator: x
  pad-right: ~
  ```
</details>
<details><summary>No `size` or `size-eos: true`</summary>

The size of an attribute is defined implicitly by absence of any size-related keys:
* ```yaml
  #          /==\ - type
  # Stream: [____                  ]         |
  #         0                  terminator    eos
  #          \_available for type_/         /
  #           \__consumed bytes__/         /
  #            \_____________stream size__/
  terminator: x
  ```
* `pad-right` implicitly defines `terminator` but this is lead to an error:
  ```yaml
  # (main): /seq/0: error: 'size', 'size-eos' or 'terminator' must be specified
  #          /==\ - type           /===\ - padding
  # Stream: [____                  ~~~~~]    |
  #         0                                eos
  #          \_available for type_/    /    /
  #           \_____consumed bytes____/    /
  #            \_____________stream size__/
  pad-right: ~
  # terminator: ~ - implicit
  ```
* `pad-right` is useless, but this is not forbidden:
  ```yaml
  #          /==\ - type
  # Stream: [____                  ]         |
  #         0                  terminator    eos
  #          \_available for type_/         /
  #           \__consumed bytes__/         /
  #            \_____________stream size__/
  terminator: x
  pad-right: ~
  ```
</details>

# Problem 1 -- `size` and `size-eos` handled inconsistently depending on the type kind
I found, that `size` and `size-eos` keys won't work with built-in types with known size (`u1`, etc.):
```yaml
- id: field
  type: u4 # and other sized built-ins
  # Compile-time error
  # io.kaitai.struct.format.YAMLParseException: /seq/0/size: unknown key found, expected: consume, doc, doc-ref, eos-error, id, if, include, repeat, terminator, type, valid
  # size: 10
  # Compile-time error
  # size-eos: true
```
At the same time you can specify `terminator` key, but it seams it has no meaning for that case:
```yaml
- id: field
  # result: 0x504b0304
  type: u4be # and other sized built-ins
  # on input [50 4b 03 04]
  terminator: 3
```

# Inconsistency 2 -- `pad-right` can not be used alone
When `pad-right: x` used together with the `size` or `size-eos: true`, it is implicitly defines a `terminator: x` if the value of the terminator is not defined explicitly or implicitly by `strz`.
```yaml
size-eos: true
pad-right: y
# terminator: y - implicit
```
```yaml
size: x
pad-right: y
# terminator: y - implicit
```

Also, it is possible to define only a `terminator` without `size` or `size-eos: true`:
```yaml
terminator: x
```
```yaml
terminator: x
pad-right: y
```

At the same time defining only the `pad-right` is an error:
```yaml
# (main): /seq/0: error: 'size', 'size-eos' or 'terminator' must be specified
pad-right: ~
# terminator: ~ - implicit
```

# Solution
I think, it will more consistent, if size-related keys will be independent from types. Each kaitai stream must have 4 properties:
- start offset
- consumed size
- availible size for sub-streams. That size is different from "consumed size" when terminator and/or pad-right is used. Technically more convenient to store as an end offset
- local current offset -- used as base for `pos` keys

At start root stream have:
- start offset = 0
- local current offset = start offset
- consumed size = undefined
- end offset = start offset + data size

Parsing will run as follows (`current_offset` -- global offset in parsed data):
1. Create new sub-stream of specified size
    - `start_offset = current_offset`
    - `end_offset = parent_stream.end_offset`
    - `local_current_offset = parent_stream.local_current_offset`
    - `consumed_size = undefined`
    - if `size` specified, `consumed_size = <size>, end_offset = start_offset + <size>, local_current_offset = 0`
    - if `size-eos: true` specified, `local_current_offset = 0`
2. If `terminator` specified, find first `terminator` in sub-stream, and limit stream availible size
    - `local_current_offset = 0`
    - if terminator NOT found
      - if `eos-error: true` raise error, stop
      - if `consumed_size` is not defined, `consumed_size = end_offset - start_offset`
    - if terminator found
      - `end_offset = <position of terminator>`
      - if `include: true` specified, `end_offset = end_offset + 1`
      - if `consumed_size` is not defined
        - `consumed_size = <position of terminator> - start_offset`
        - if `consume: true` specified, `consumed_size = consumed_size + 1`
3. If terminator NOT found and `pad-right` specified, find first `pad-right` in sub-stream, and limit stream availible size
    - if padding byte(s) found, `end_offset = <position of start padding>`
4. Read specified type, using `[start_offset, end_offset)` slice as source of data
    - if type is built-in type, call corresponding built-in function
      - fixed sized types read only necessary part of buffer, other is unused
      - variable sized types (`str`, `strz` and `bytes`) use entire buffer as result
    - if type is user type, recursively repeat this algorithm for all fields of user type
    - if type is opaque type, call read function of opaque type
5. If `consumed_size` is not defined, set `consumed_size = <readed size>`
6. `current_offset = start_offset + consumed_size`

That algorithm also fixes #783