A Discrete-Event Network Simulator
API
Loading...
Searching...
No Matches
bit-serializer.cc
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Universita' di Firenze, Italy
3 *
4 * SPDX-License-Identifier: GPL-2.0-only
5 *
6 * Author: Tommaso Pecorella <tommaso.pecorella@unifi.it>
7 */
8
9#include "ns3/bit-serializer.h"
10
11#include "ns3/bit-deserializer.h"
12
13#include <iostream>
14
15using namespace ns3;
16
17// The main purpose of the BitSerializer and bitDeserializer classes is to
18// simplify the bit serialization and deserialization in headers, trailers
19// and packet bodies.
20//
21// This is usually performed by using bit masks, which works great if the
22// field delimiters are known in advance, and are in a fixed position.
23// If the field (i.e., a group of bits) position is dependent from some
24// other parameter, then the code is more complex.
25// If the field boundary is not even a multiple of a byte, then the problem
26// is even more complex.
27//
28// BitSerializer allows you to "push" bits into a temporary buffer, and then
29// extract an array of uint8_t to be used in
30// Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
31//
32// Similarly, BitDeserializer can be initialized by an array of uint8_t,
33// typically obtained by a Buffer::Iterator:Read (uint8_t *buffer, uint32_t size)
34// and then "pop" bits from the underlying buffer.
35//
36// This example shows the basic operations.
37
38int
39main()
40{
41 BitSerializer testBitSerializer1;
42
43 // add 7 bits - 0x55 (101 0101)
44 testBitSerializer1.PushBits(0x55, 7);
45 // add 3 bits - 0x7 (111)
46 testBitSerializer1.PushBits(0x7, 3);
47 // add 2 bits - 0x0 (00)
48 testBitSerializer1.PushBits(0x0, 2);
49 // The results is 1010 1011 1100.
50 // Adding 4 bits of padding at the end the result is 0xabc0.
51
52 std::vector<uint8_t> result = testBitSerializer1.GetBytes();
53
54 std::cout << "Result: ";
55 for (std::size_t i = 0; i < result.size(); i++)
56 {
57 std::cout << std::hex << int(result[i]) << " ";
58 }
59 std::cout << std::endl;
60 std::cout << "Expecting: ab c0" << std::endl;
61
62 // Here, instead of printing bits, you typically serialize them using
63 // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
64 //
65 // In this case the number of bits pushed is not a multiple of a byte
66 // so the class adds a padding at the end of the buffer.
67 // This is the default behaviour.
68
69 BitSerializer testBitSerializer2;
70
71 // add 7 bits - 0x55 (101 0101)
72 testBitSerializer2.PushBits(0x55, 7);
73 // add 3 bits - 0x7 (111)
74 testBitSerializer2.PushBits(0x7, 3);
75 // add 2 bits - 0x0 (00)
76 testBitSerializer2.PushBits(0x0, 2);
77
78 // Change the class behaviour so to use a padding at the start of the buffer.
79 testBitSerializer2.InsertPaddingAtEnd(false);
80 // The results is 1010 1011 1100.
81 // Adding 4 bits of padding at the start the result is 0xabc.
82
83 result = testBitSerializer2.GetBytes();
84
85 std::cout << "Result: ";
86 for (std::size_t i = 0; i < result.size(); i++)
87 {
88 std::cout << std::hex << int(result[i]) << " ";
89 }
90 std::cout << std::endl;
91 std::cout << "Expecting: a bc" << std::endl;
92
93 // Here, instead of printing bits, you typically serialize them using
94 // Buffer::Iterator:Write (uint8_t const *buffer, uint32_t size).
95 //
96 // In this case the number of bits pushed is not a multiple of a byte
97 // so the class adds a padding at the start of the buffer.
98
99 BitDeserializer testBitDeserializer;
100 uint8_t test[2];
101 test[0] = 0xab;
102 test[1] = 0xc0;
103
104 // Typically a BitDeserializer will be initialized by an array obtained by
105 // Buffer::Iterator:Read (uint8_t *buffer, uint32_t size).
106
107 testBitDeserializer.PushBytes(test, 2);
108 uint16_t nibble1 = testBitDeserializer.GetBits(7);
109 uint8_t nibble2 = testBitDeserializer.GetBits(3);
110 uint8_t nibble3 = testBitDeserializer.GetBits(2);
111 // if you deserialize too many bits you'll get an assert.
112 // uint8_t errorNibble = testBitDeserializer.GetBits (6);
113
114 std::cout << "Result: " << std::hex << nibble1 << " " << +nibble2 << " " << +nibble3 << " "
115 << std::endl;
116 std::cout << "Expecting: 55 7 0" << std::endl;
117
118 return 0;
119}
Bit deserializer.
void PushBytes(std::vector< uint8_t > bytes)
Pushes some bytes into the blob to be deserialized.
uint64_t GetBits(uint8_t size)
Pops a given number of bits from the blob front.
Bit serializer.
void PushBits(uint64_t value, uint8_t significantBits)
Pushes a number of bits in the blob.
std::vector< uint8_t > GetBytes()
Get the bytes representation of the blob.
void InsertPaddingAtEnd(bool padAtEnd)
Toggles the padding insertion policy.
Every class exported by the ns3 library is enclosed in the ns3 namespace.
-ns3 Test suite for the ns3 wrapper script