v2 / vlib / encoding / binary / little_endian.v
288 lines · 266 sloc · 8.25 KB · 3caa1b7297e2959633adb39f1422765aba8a4d50
Raw
1// Copyright (c) 2019-2024 Alexander Medvednikov. All rights reserved.
2// Use of this source code is governed by an MIT license
3// that can be found in the LICENSE file.
4module binary
5
6// little_endian_u16 creates a u16 from the first two bytes in the array b in little endian order.
7@[direct_array_access; inline]
8pub fn little_endian_u16(b []u8) u16 {
9 _ = b[1] // bounds check
10 unsafe {
11 mut u := U16{}
12 $if little_endian {
13 u.b[0], u.b[1] = b[0], b[1]
14 } $else {
15 u.b[0], u.b[1] = b[1], b[0]
16 }
17 return u.u
18 }
19}
20
21// little_endian_u16_at creates a u16 from two bytes in the array b at the specified offset in little endian order.
22@[direct_array_access; inline]
23pub fn little_endian_u16_at(b []u8, o int) u16 {
24 _ = b[o] // bounds check
25 _ = b[o + 1] // bounds check
26 unsafe {
27 mut u := U16{}
28 $if little_endian {
29 u.b[0], u.b[1] = b[o], b[o + 1]
30 } $else {
31 u.b[0], u.b[1] = b[o + 1], b[o]
32 }
33 return u.u
34 }
35}
36
37// little_endian_u16_end creates a u16 from the last two bytes of the array b in little endian order.
38@[direct_array_access; inline]
39pub fn little_endian_u16_end(b []u8) u16 {
40 return little_endian_u16_at(b, b.len - 2)
41}
42
43// little_endian_put_u16 writes a u16 to the first two bytes in the array b in little endian order.
44@[direct_array_access; inline]
45pub fn little_endian_put_u16(mut b []u8, v u16) {
46 _ = b[1] // bounds check
47 unsafe {
48 mut u := U16{
49 u: v
50 }
51 $if little_endian {
52 b[0], b[1] = u.b[0], u.b[1]
53 } $else {
54 b[0], b[1] = u.b[1], u.b[0]
55 }
56 }
57}
58
59// little_endian_put_u16_at writes a u16 to the two bytes in the array b at the specified offset in little endian order.
60@[direct_array_access; inline]
61pub fn little_endian_put_u16_at(mut b []u8, v u16, o int) {
62 _ = b[o] // bounds check
63 _ = b[o + 1] // bounds check
64 unsafe {
65 mut u := U16{
66 u: v
67 }
68 $if little_endian {
69 b[o], b[o + 1] = u.b[0], u.b[1]
70 } $else {
71 b[o], b[o + 1] = u.b[1], u.b[0]
72 }
73 }
74}
75
76// little_endian_put_u16_end writes a u16 to the last two bytes of the array b in little endian order.
77@[direct_array_access; inline]
78pub fn little_endian_put_u16_end(mut b []u8, v u16) {
79 little_endian_put_u16_at(mut b, v, b.len - 2)
80}
81
82// little_endian_get_u16 creates u8 array from the unsigned 16-bit integer v in little endian order.
83pub fn little_endian_get_u16(v u16) []u8 {
84 unsafe {
85 mut u := U16{
86 u: v
87 }
88 $if big_endian {
89 u.b[0], u.b[1] = u.b[1], u.b[0]
90 }
91 return u.b[..]
92 }
93}
94
95// little_endian_u32 creates a u32 from the first four bytes in the array b in little endian order.
96@[direct_array_access; inline]
97pub fn little_endian_u32(b []u8) u32 {
98 _ = b[3] // bounds check
99 unsafe {
100 mut u := U32{}
101 $if little_endian {
102 u.b[0], u.b[1], u.b[2], u.b[3] = b[0], b[1], b[2], b[3]
103 } $else {
104 u.b[0], u.b[1], u.b[2], u.b[3] = b[3], b[2], b[1], b[0]
105 }
106 return u.u
107 }
108}
109
110// little_endian_u32_at creates a u32 from four bytes in the array b at the specified offset in little endian order.
111@[direct_array_access; inline]
112pub fn little_endian_u32_at(b []u8, o int) u32 {
113 _ = b[o] // bounds check
114 _ = b[o + 3] // bounds check
115 unsafe {
116 mut u := U32{}
117 $if little_endian {
118 u.b[0], u.b[1], u.b[2], u.b[3] = b[o], b[o + 1], b[o + 2], b[o + 3]
119 } $else {
120 u.b[0], u.b[1], u.b[2], u.b[3] = b[o + 3], b[o + 2], b[o + 1], b[o]
121 }
122 return u.u
123 }
124}
125
126// little_endian_u32_end creates a u32 from the last four bytes in the array b in little endian order.
127@[direct_array_access; inline]
128pub fn little_endian_u32_end(b []u8) u32 {
129 return little_endian_u32_at(b, b.len - 4)
130}
131
132// little_endian_put_u32 writes a u32 to the first four bytes in the array b in little endian order.
133@[direct_array_access; inline]
134pub fn little_endian_put_u32(mut b []u8, v u32) {
135 _ = b[3] // bounds check
136 unsafe {
137 mut u := U32{
138 u: v
139 }
140 $if little_endian {
141 b[0], b[1], b[2], b[3] = u.b[0], u.b[1], u.b[2], u.b[3]
142 } $else {
143 b[0], b[1], b[2], b[3] = u.b[3], u.b[2], u.b[1], u.b[0]
144 }
145 }
146}
147
148// little_endian_put_u32_at writes a u32 to the four bytes in the array b at the specified offset in little endian order.
149@[direct_array_access; inline]
150pub fn little_endian_put_u32_at(mut b []u8, v u32, o int) {
151 _ = b[o] // bounds check
152 _ = b[o + 3] // bounds check
153 unsafe {
154 mut u := U32{
155 u: v
156 }
157 $if little_endian {
158 b[o], b[o + 1], b[o + 2], b[o + 3] = u.b[0], u.b[1], u.b[2], u.b[3]
159 } $else {
160 b[o], b[o + 1], b[o + 2], b[o + 3] = u.b[3], u.b[2], u.b[1], u.b[0]
161 }
162 }
163}
164
165// little_endian_put_u32_end writes a u32 to the last four bytes in the array b in little endian order.
166@[direct_array_access; inline]
167pub fn little_endian_put_u32_end(mut b []u8, v u32) {
168 little_endian_put_u32_at(mut b, v, b.len - 4)
169}
170
171// little_endian_get_u32 creates u8 array from the unsigned 32-bit integer v in little endian order.
172pub fn little_endian_get_u32(v u32) []u8 {
173 unsafe {
174 mut u := U32{
175 u: v
176 }
177 $if big_endian {
178 u.b[0], u.b[1], u.b[2], u.b[3] = u.b[3], u.b[2], u.b[1], u.b[0]
179 }
180 return u.b[..]
181 }
182}
183
184// little_endian_u64 creates a u64 from the first eight bytes in the array b in little endian order.
185@[direct_array_access; inline]
186pub fn little_endian_u64(b []u8) u64 {
187 _ = b[7] // bounds check
188 unsafe {
189 mut u := U64{}
190 $if little_endian {
191 u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7] = b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]
192 } $else {
193 u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7] = b[7], b[6], b[5], b[4], b[3], b[2], b[1], b[0]
194 }
195 return u.u
196 }
197}
198
199// little_endian_u64_at creates a u64 from eight bytes in the array b at the specified offset in little endian order.
200@[direct_array_access; inline]
201pub fn little_endian_u64_at(b []u8, o int) u64 {
202 _ = b[o] // bounds check
203 _ = b[o + 7] // bounds check
204 unsafe {
205 mut u := U64{}
206 $if little_endian {
207 u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7] = b[o], b[o + 1], b[o + 2], b[
208 o + 3], b[o + 4], b[o + 5], b[o + 6], b[o + 7]
209 } $else {
210 u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7] = b[o + 7], b[o + 6], b[
211 o + 5], b[o + 4], b[o + 3], b[o + 2], b[o + 1], b[o]
212 }
213 return u.u
214 }
215}
216
217// little_endian_u64_end creates a u64 from the last eight bytes in the array b in little endian order.
218@[direct_array_access; inline]
219pub fn little_endian_u64_end(b []u8) u64 {
220 return little_endian_u64_at(b, b.len - 8)
221}
222
223// little_endian_put_u64 writes a u64 to the first eight bytes in the array b in little endian order.
224@[direct_array_access; inline]
225pub fn little_endian_put_u64(mut b []u8, v u64) {
226 _ = b[7] // bounds check
227 unsafe {
228 mut u := U64{
229 u: v
230 }
231 $if little_endian {
232 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] = u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7]
233 } $else {
234 b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7] = u.b[7], u.b[6], u.b[5], u.b[4], u.b[3], u.b[2], u.b[1], u.b[0]
235 }
236 }
237}
238
239// little_endian_put_u64_at writes a u64 to the eight bytes in the array b at the specified offset in little endian order.
240@[direct_array_access; inline]
241pub fn little_endian_put_u64_at(mut b []u8, v u64, o int) {
242 _ = b[o] // bounds check
243 _ = b[o + 7] // bounds check
244 unsafe {
245 mut u := U64{
246 u: v
247 }
248 $if little_endian {
249 b[o], b[o + 1], b[o + 2], b[o + 3], b[o + 4], b[o + 5], b[o + 6], b[o + 7] = u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7]
250 } $else {
251 b[o], b[o + 1], b[o + 2], b[o + 3], b[o + 4], b[o + 5], b[o + 6], b[o + 7] = u.b[7], u.b[6], u.b[5], u.b[4], u.b[3], u.b[2], u.b[1], u.b[0]
252 }
253 }
254}
255
256// little_endian_put_u64_end writes a u64 to the last eight bytes in the array b at in little endian order.
257@[direct_array_access; inline]
258pub fn little_endian_put_u64_end(mut b []u8, v u64) {
259 little_endian_put_u64_at(mut b, v, b.len - 8)
260}
261
262@[direct_array_access; inline]
263pub fn little_endian_f32_at(b []u8, o int) f32 {
264 _ = b[o] // bounds check
265 _ = b[o + 3] // bounds check
266 unsafe {
267 mut u := F32{}
268 $if little_endian {
269 u.b[0], u.b[1], u.b[2], u.b[3] = b[o], b[o + 1], b[o + 2], b[o + 3]
270 } $else {
271 u.b[0], u.b[1], u.b[2], u.b[3] = b[o + 3], b[o + 2], b[o + 1], b[o]
272 }
273 return u.u
274 }
275}
276
277// little_endian_get_u64 creates u8 array from the unsigned 64-bit integer v in little endian order.
278pub fn little_endian_get_u64(v u64) []u8 {
279 unsafe {
280 mut u := U64{
281 u: v
282 }
283 $if big_endian {
284 u.b[0], u.b[1], u.b[2], u.b[3], u.b[4], u.b[5], u.b[6], u.b[7] = u.b[7], u.b[6], u.b[5], u.b[4], u.b[3], u.b[2], u.b[1], u.b[0]
285 }
286 return u.b[..]
287 }
288}
289