Skip to content

Commit 8c63279

Browse files
committed
feat(state_format): add DHT section and its de-serialization
Also move function for safe casing `u32 → array` from tests to binary_io, make it public, and add test for it.
1 parent 85508e1 commit 8c63279

File tree

3 files changed

+84
-10
lines changed

3 files changed

+84
-10
lines changed

src/toxcore/binary_io.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ pub fn array_to_u32(array: &[u8; 4]) -> u32 {
6666
result
6767
}
6868

69+
/// Safely cast `u32` to `[u8; 4]`.
70+
pub fn u32_to_array(num: u32) -> [u8; 4] {
71+
let mut array: [u8; 4] = [0; 4];
72+
for (pos, item) in array.iter_mut().enumerate() {
73+
*item = (num >> (8 * pos)) as u8;
74+
}
75+
array
76+
}
6977

7078
/// Safely cast `&[u8; 8]` to `u64`.
7179
pub fn array_to_u64(array: &[u8; 8]) -> u64 {

src/toxcore/state_format/old.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
2323
use toxcore::binary_io::*;
2424
use toxcore::crypto_core::*;
25+
use toxcore::dht::*;
2526
use toxcore::toxid::{NoSpam, NOSPAMBYTES};
2627

2728
// TODO: improve docs
@@ -265,3 +266,62 @@ impl ToBytes for NospamKeys {
265266
result
266267
}
267268
}
269+
270+
271+
/** DHT section of the old state format.
272+
273+
https://zetok.github.io/tox-spec/#dht-0x02
274+
275+
Serialized format
276+
*/
277+
#[derive(Clone, Debug, Eq, PartialEq)]
278+
pub struct DhtState(pub Vec<PackedNode>);
279+
280+
/// Minimal number of bytes [`DhtState`](./struct.DhtState.html) has.
281+
///
282+
/// Assumes that at least all the magic numbers are present.
283+
const DHT_STATE_SIZE_MIN: usize = 12;
284+
285+
/// Special, magical beginning of DHT section in LE.
286+
const DHT_MAGICAL: u32 = 0x159000d;
287+
288+
/** Special DHT section type encoded in LE.
289+
290+
https://zetok.github.io/tox-spec/#dht-sections
291+
*/
292+
const DHT_SECTION_TYPE: u16 = 0x04;
293+
294+
/** Yet another magical number in DHT section that needs a check.
295+
296+
https://zetok.github.io/tox-spec/#dht-sections
297+
*/
298+
const DHT_2ND_MAGICAL: u16 = 0x11ce;
299+
300+
/** If successful, returns `DhtState` and length of the section in bytes.
301+
302+
If de-serialization failed, returns `None`.
303+
*/
304+
// TODO: better docs; list when can fail
305+
impl FromBytes<(DhtState, usize)> for (DhtState, usize) {
306+
fn from_bytes(bytes: &[u8]) -> Option<Self> {
307+
if
308+
bytes.len() < DHT_STATE_SIZE_MIN ||
309+
// check whether beginning of the section matches DHT magic bytes
310+
&u32_to_array(DHT_MAGICAL.to_le()) != &bytes[..4] ||
311+
// check DHT section type
312+
&u16_to_array(DHT_SECTION_TYPE.to_le()) != &bytes[8..10] ||
313+
// check whether yet another magic number matches ;f
314+
&u16_to_array(DHT_2ND_MAGICAL.to_le()) != &bytes[10..12]
315+
{ return None } // can I haz yet another magical number?
316+
317+
// length of the whole section
318+
let section_len = {
319+
let nodes = array_to_u32(&[bytes[4], bytes[5], bytes[6], bytes[7]]);
320+
u32::from_le(nodes) as usize + DHT_STATE_SIZE_MIN
321+
};
322+
323+
PackedNode::from_bytes_multiple(&bytes[DHT_STATE_SIZE_MIN..section_len])
324+
.map(|pns| (DhtState(pns), section_len))
325+
}
326+
}
327+
// TODO: test ↑

src/toxcore_tests/binary_io_tests.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,22 +25,15 @@ use toxcore::binary_io::*;
2525

2626

2727
fn u16_to_array_and_back(num: u16) {
28-
assert!(num == array_to_u16(&u16_to_array(num)));
28+
assert_eq!(num, array_to_u16(&u16_to_array(num)));
2929
}
3030

31-
fn u32_to_array(num: u32) -> [u8; 4] {
32-
let mut array: [u8; 4] = [0; 4];
33-
for (pos, item) in array.iter_mut().enumerate() {
34-
*item = (num >> (8 * pos)) as u8;
35-
}
36-
array
37-
}
3831
fn u32_to_array_and_back(num: u32) {
39-
assert!(num == array_to_u32(&u32_to_array(num)));
32+
assert_eq!(num, array_to_u32(&u32_to_array(num)));
4033
}
4134

4235
fn u64_to_array_and_back(num: u64) {
43-
assert!(num == array_to_u64(&u64_to_array(num)));
36+
assert_eq!(num, array_to_u64(&u64_to_array(num)));
4437
}
4538

4639
#[test]
@@ -77,6 +70,19 @@ fn array_to_u32_test() {
7770
quickcheck(u32_to_array_and_back as fn(u32));
7871
}
7972

73+
#[test]
74+
fn u32_to_array_test() {
75+
assert_eq!([0, 0, 0, 0], u32_to_array(0));
76+
assert_eq!([1, 0, 0, 0], u32_to_array(1));
77+
assert_eq!([0, 1, 0, 0], u32_to_array(256));
78+
assert_eq!([0, 0, 1, 0], u32_to_array(65536));
79+
assert_eq!([0, 0, 0, 1], u32_to_array(16777216));
80+
assert_eq!([0, 0, 0, 0xff], u32_to_array(4278190080));
81+
assert_eq!([0xff, 0xff, 0xff, 0xff], u32_to_array(u32::max_value()));
82+
83+
quickcheck(u32_to_array_and_back as fn(u32));
84+
}
85+
8086
#[test]
8187
fn array_to_u64_test() {
8288
assert_eq!(array_to_u64(&[0, 0, 0, 0, 0, 0, 0, 0]), 0);

0 commit comments

Comments
 (0)