1#include <string.h>
2
3#include "net/packet.h"
4
5static i8 packet_read(PacketReader* reader, void* output, size_t size);
6
7/* read a number of bytes from packet, copy them to output.
8 returns 1 on success, 0 on failure */
9static i8 packet_read(PacketReader* reader, void* output, size_t size)
10{
11 if (reader->cursor > reader->size)
12 return 0;
13
14 if (size > reader->size - reader->cursor)
15 return 0;
16
17 memcpy(output, reader->data + reader->cursor, size);
18 reader->cursor += size;
19 return 1;
20}
21
22PacketReader packet_reader_init(const void* data, size_t size)
23{
24 PacketReader reader = { data, size, 0 };
25 return reader;
26}
27
28i8 packet_read_u8(PacketReader* reader, u8* value)
29{
30 return packet_read(reader, value, 1);
31}
32
33i8 packet_read_u16(PacketReader* reader, u16* value)
34{
35 u8 data[2];
36
37 if (!packet_read(reader, data, 2))
38 return 0;
39
40 *value = ((u16)data[0] << 8) | (u16)data[1];
41
42 return 1;
43}
44
45i8 packet_read_i32(PacketReader* reader, i32* value)
46{
47 u8 data[4];
48 u32 result;
49
50 if (!packet_read(reader, data, 4))
51 return 0;
52
53 result = ((u32)data[0] << 24) | ((u32)data[1] << 16) | ((u32)data[2] << 8) | (u32)data[3];
54
55 *value = (i32)result;
56 return 1;
57}
58
59i8 packet_read_u64(PacketReader* reader, u64* value)
60{
61 u8 data[8];
62 u64 result;
63 i32 i;
64
65 if (!packet_read(reader, data, 8))
66 return 0;
67
68 result = 0;
69
70 for (i = 0; i < 8; i++)
71 result = (result << 8) | data[i];
72
73 *value = result;
74 return 1;
75}
76
77i8 packet_read_f32(PacketReader* reader, float* value)
78{
79 i32 bits;
80
81 if (!packet_read_i32(reader, &bits))
82 return 0;
83
84 memcpy(value, &bits, sizeof(*value));
85 return 1;
86}
87
88i8 packet_read_f64(PacketReader* reader, double* value)
89{
90 u64 bits;
91
92 if (!packet_read_u64(reader, &bits))
93 return 0;
94
95 memcpy(value, &bits, sizeof(*value));
96 return 1;
97}
98
99i8 packet_read_varint(PacketReader* reader, i32* value)
100{
101 u32 result;
102 u8 byte;
103 i32 shift;
104
105 result = 0;
106
107 for (shift = 0; shift < 7 * 5; shift += 7) { /* varints have max 5 bytes */
108 if (!packet_read_u8(reader, &byte))
109 return 0;
110
111 result |= (u32)(byte & 0x7f) << shift;
112
113 if (!(byte & 0x80)) { /* last byte */
114 *value = (i32)result;
115 return 1;
116 }
117 }
118
119 return 0;
120}