Skip to content

Commit 1fb4f2b

Browse files
committed
Update README
Update docs workflow
1 parent e20b5cb commit 1fb4f2b

File tree

3 files changed

+90
-25
lines changed

3 files changed

+90
-25
lines changed

.github/workflows/docs.yml

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
11
name: Docs
22

33
on:
4+
push:
5+
branches: [ master ]
6+
paths: '**/*.md'
47
workflow_dispatch:
5-
inputs:
6-
tagName:
7-
description: 'Test'
8-
type: boolean
98

109
jobs:
11-
Docs:
10+
Build:
1211
runs-on: ubuntu-latest
1312
permissions:
1413
actions: read
15-
contents: write
16-
pull-requests: write
14+
contents: read
1715
steps:
1816
- name: Checkout
1917
uses: actions/checkout@v3
@@ -24,14 +22,29 @@ jobs:
2422
path: doxygen-awesome-css
2523
- name: Install doxygen
2624
run: sudo apt-get update && sudo apt-get install doxygen graphviz -y
27-
- name: Generate Doxygen Documentation
25+
- name: Generate Doxygen documentation
2826
run: doxygen Doxyfile
2927
- name: Copy LICENSE
3028
run: cp doxygen-awesome-css/LICENSE docs/html/LICENSE
3129
- name: Create .nojekyll
3230
run: touch docs/html/.nojekyll
33-
- name: Deploy Documentation to branch
34-
uses: JamesIves/github-pages-deploy-action@v4
31+
- name: Upload documentation
32+
uses: actions/upload-pages-artifact@v1
3533
with:
36-
branch: docs
37-
folder: docs/html
34+
path: docs/html
35+
Deploy:
36+
needs: Build
37+
runs-on: ubuntu-latest
38+
environment:
39+
name: github-pages
40+
url: ${{ steps.deployment.outputs.page_url }}
41+
permissions:
42+
actions: read
43+
contents: read
44+
pages: write
45+
id-token: write
46+
name: Deploy
47+
steps:
48+
- name: Deploy documentation
49+
id: deployment
50+
uses: actions/deploy-pages@v1

.github/workflows/main.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
paths-ignore:
99
- '**/*.md'
1010
- '**/*.gitignore'
11+
- '**/Doxyfile'
1112

1213
jobs:
1314
Build:

README.md

Lines changed: 64 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,11 @@ Based on [Glenn Fiedler's articles](https://gafferongames.com/post/reading_and_w
3232
* [Bounded float - bounded_range](#bounded-float---bounded_range)
3333
* [Quaternion - smallest_three\<Q, BitsPerElement\>](#quaternion---smallest_threeq-bitsperelement)
3434
* [Serialization Examples](#serialization-examples)
35+
* [Extensibility](#extensibility)
36+
* [Adding new serializables types](#adding-new-serializables-types)
37+
* [Unified serialization](#unified-serialization)
38+
* [Partial trait specializations](#partial-trait-specializations)
39+
* [Trait deduction](#trait-deduction)
3540
* [Building and running tests](#building-and-running-tests)
3641
* [3rd party](#3rd-party)
3742
* [License](#license)
@@ -50,20 +55,21 @@ The source and header files inside the `src/` directory are only tests and shoul
5055
# Usage
5156
The library has a global header file ([`bitstream/bitstream.h`](https://github.com/KredeGC/BitStream/tree/master/include/bitstream/bitstream.h)) which includes every other header file in the library.
5257

53-
If you only need certain features, you can simply include the files you need.
58+
If you only need certain features you can instead opt to just include the files you need.
5459
The files are stored in categories:
5560
* [`quantization/`](https://github.com/KredeGC/BitStream/tree/master/include/bitstream/quantization/) - Files relating to quantizing floats and quaternions into fewer bits
5661
* [`stream/`](https://github.com/KredeGC/BitStream/tree/master/include/bitstream/stream/) - Files relating to streams that read and write bits
5762
* [`traits/`](https://github.com/KredeGC/BitStream/tree/master/include/bitstream/traits/) - Files relating to various serialization traits, like serializble strings, integrals etc.
5863

5964
An important aspect of the serialiaztion is performance, since the library is meant to be used in a tight loop, like with networking.
6065
This is why most operations don't use exceptions, but instead return true or false depending on whether the operation was a success.
61-
It's important to check these return values after every operation, especially when reading.
66+
It's important to check these return values after every operation, especially when reading from an unknown source.
6267
You can check it manually or use the `BS_ASSERT(x)` macro for this, if you want your function to return false on failure.
6368

6469
It is also possible to dynamically put a break point or trap when a bitstream would have otherwise returned false. This can be great for debugging custom serialization code, but should generally be left out of production code. Simply `#define BS_DEBUG_BREAK` before including any of the library header files if you want to break when an operation fails.
6570

66-
For more examples of usage, see the [Serialization Examples](#serialization-examples) below.
71+
For more concrete examples of usage, see the [Serialization Examples](#serialization-examples) below.
72+
If you need to add your own serializable types you should also look at the [Extensibility](#extensibility) section.
6773
You can also look at the unit tests to get a better idea about what you can expect from the library.
6874

6975
# Documentation
@@ -350,6 +356,8 @@ The library is made with extensibility in mind.
350356
The `bit_writer` and `bit_reader` use a template trait specialization of the given type to deduce how to serialize and deserialize the object.
351357
The only requirements of the trait is that it has (or can deduce) 2 static functions which take a bit_writer& and a bit_reader& respectively as their first argument.
352358
The 2 functions must also return a bool indicating whether the serialization was a success or not, but can otherwise take any number of additional arguments.
359+
360+
## Adding new serializables types
353361
The general structure of a trait looks like the following:
354362

355363
```cpp
@@ -366,27 +374,35 @@ struct serialize_traits<TRAIT_TYPE> // The type to use when referencing this spe
366374
};
367375
```
368376
369-
Note that `TRAIT_TYPE` does not necessarily have to be part of the serialize function definitions.
370-
It is purely used to specify which trait to use when serializing, since it cannot be deduced from the arguments.<br/>
371-
To use the trait above to serialize an object you need to explicitly specify it:
372-
```cpp
373-
bool status = writer.serialize<TRAIT_TYPE>(...);
374-
```
375-
376-
The specialization can also be unified with templating, if writing and reading look similar:
377+
## Unified serialization
378+
The serialization can also be unified with templating, if writing and reading look similar.
379+
If some parts of the serialization process don't match entirely you can query the `Stream::reading` or `Stream::writing` and branch depending on the value.
380+
An example of this can be seen below:
377381
```cpp
378382
template<>
379383
struct serialize_traits<TRAIT_TYPE> // The type to use when serializing
380384
{
381385
// Will be called when writing or reading the object to a stream
382386
template<typename Stream>
383387
static bool serialize(Stream& stream, ...)
384-
{ ... }
388+
{
389+
// Some code that looks the same for writing and reading
390+
391+
if constexpr (Stream::writing) {
392+
// Code that should only be run when writing
393+
}
394+
395+
// A variable that differs if the stream is writing or reading
396+
int value = Stream::reading ? 0 : 1;
397+
398+
...
399+
}
385400
};
386401
```
387402

403+
## Partial trait specializations
388404
The specialization can also be templated to work with a number of types.
389-
It also works with `enable_if`:
405+
It also works with `enable_if` as the second argument:
390406
```cpp
391407
// This trait will be used by any non-const integral pointer type (char*, uint16_t* etc.)
392408
template<typename T>
@@ -398,6 +414,41 @@ bool status = writer.serialize<int16_t*>(...);
398414
bool status = writer.serialize<const int16_t*>(...);
399415
```
400416
417+
Note that `TRAIT_TYPE` does not necessarily have to be part of the serialize function definitions.
418+
It can just be used to specify which trait to use when serializing, if it cannot be deduced from the arguments.<br/>
419+
Below is an example where we serialize an object by explicitly defining the trait type:
420+
```cpp
421+
bool status = writer.serialize<TRAIT_TYPE>(...);
422+
```
423+
424+
## Trait deduction
425+
When calling the `serialize` function on a `bit_writer` or `bit_reader`, the trait can sometimes be deduced instead of being explicitly declared.
426+
This can only be done if the type of the second argument in the `static bool serialize(...)` function is (roughly) the same as the trait type.
427+
An example of the structure for an implicit trait can be seen below:
428+
```cpp
429+
template<>
430+
struct serialize_traits<TRAIT_TYPE> // The type to use when referencing this specific trait
431+
{
432+
// The second argument is the same as TRAIT_TYPE (const and lvalue references are removed when deducing)
433+
static bool serialize(bit_writer& stream, const TRAIT_TYPE&, ...)
434+
{ ... }
435+
436+
// The second argument is the same as TRAIT_TYPE (lvalue is removed)
437+
static bool serialize(bit_reader& stream, TRAIT_TYPE&, ...)
438+
{ ... }
439+
};
440+
```
441+
442+
The above trait could then be used when implicitly serializing an object of type `TRAIT_TYPE`:
443+
```cpp
444+
TRAIT_TYPE value;
445+
bool status = writer.serialize(value, ...);
446+
```
447+
448+
It doesn't work on all types, and there is some guesswork involved relating to const qualifiers.
449+
E.g. a trait of type `char` is treated the same as `const char&` and thus the call would be ambiguous if both had a trait specialization.
450+
In case of ambiguity you will still be able to declare the trait explicitly when calling the `serialize` function.
451+
401452
More concrete examples of traits can be found in the [`traits/`](https://github.com/KredeGC/BitStream/tree/master/include/bitstream/traits/) directory.
402453

403454
# Building and running tests

0 commit comments

Comments
 (0)