Решение на Network Packets от Ангел Беширов
Резултати
- 19 точки от тестове
- 1 бонус точка
- 20 точки общо
- 14 успешни тест(а)
- 1 неуспешни тест(а)
Код
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20200111-2173579-ofw977/solution) Finished test [unoptimized + debuginfo] target(s) in 5.02s Running target/debug/deps/solution-a73e64ec87929bd0 running 35 tests test test_basic_iteration ... ok test test_basic_multibyte ... ok test test_basic_multibyte_2 ... ok test test_basic_multiple_packets ... ok test test_basic_packets ... ok test test_basic_packets_bigger_size ... ok test test_complete_deserialization ... ok test test_complex_mutlibyte ... ok test test_corrupted_message_invalid_sparkle ... ok test test_deserialize_basic_packet ... ok test test_deserialize_invalid_checksum ... ok test test_deserialize_invalid_checksum_because_of_wrong_size ... ok test test_deserialize_invalid_packet ... ok test test_deserialize_missing_checksum ... ok test test_deserialize_overflow_size ... ok test test_deserialize_packet_with_size_0 ... ok test test_deserialize_the_smallest_packet ... ok test test_deserialize_too_small_slices ... ok test test_deserialize_unknown_version_error ... ok test test_deserialize_unknown_version_string ... ok test test_empty_slice_deserialization ... ok test test_empty_string ... ok test test_empty_string_deserialize ... ok test test_empty_string_for_to_packet_data ... ok test test_incomplete_deserialization ... ok test test_invalid_checksum ... ok test test_large_multibyte_string ... ok test test_next_on_empty_iterator ... ok test test_serialization_basic_larger_size ... ok test test_serialization_basic_small_size ... ok test test_serialization_empty ... ok test test_serialization_iterations ... ok test test_serialize ... ok test test_size_zero_for_to_packet_data ... ok test test_sparkle ... ok test result: ok. 35 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Running target/debug/deps/solution_test-38971695424b36d5 running 15 tests test solution_test::test_construct_packet_from_unicode ... ok test solution_test::test_construct_packet_no_remainder ... ok test solution_test::test_construct_packet_with_remainder ... ok test solution_test::test_construct_packet_with_remainder_cyrillic ... ok test solution_test::test_consuming_packets ... ok test solution_test::test_deserialize_invalid_packet ... ok test solution_test::test_deserialize_packet ... ok test solution_test::test_deserialize_unicode_packet ... ok test solution_test::test_full_roundtrip ... ok test solution_test::test_full_roundtrip_for_zero_size_string ... thread '<unnamed>' panicked at 'Can not deserialize empty bytes slice', src/lib.rs:74:13 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace. FAILED test solution_test::test_invalid_packet_combination ... ok test solution_test::test_iterating_packets ... ok test solution_test::test_iterating_packets_for_zero_size_string ... ok test solution_test::test_serialize_packet ... ok test solution_test::test_zero_size ... ok failures: ---- solution_test::test_full_roundtrip_for_zero_size_string stdout ---- thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21 failures: solution_test::test_full_roundtrip_for_zero_size_string test result: FAILED. 14 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out error: test failed, to rerun pass '--test solution_test'
История (4 версии и 6 коментара)
Ангел качи решение на 03.12.2019 02:28 (преди почти 6 години)
Ангел качи решение на 03.12.2019 02:30 (преди почти 6 години)
Ангел качи решение на 03.12.2019 12:46 (преди почти 6 години)
Няма нужда да използваш различно име -- можеше да е let size = {
и този size
да скрие оригиналната стойност. По този начин се подсигуряваш, че всякаква употреба на size
надолу е правилния размер. Иначе има шанса някой да меши real_size
и size
и потенциално да допусне тънък бъг.
При нулев размер се очаква InvalidPacket
, но това мисля, че вече го обсъдихме в discord.
Вместо да вземаш tuple
и после да достъпваш елементите с tuple.1
и tuple.0
(които не са много ясни имена), можеше да дефинираш две променливи с присвояването:
let (packet, remainder) = Packet::from_source(&cloned, self.packet_size);
self.data = remainder.to_vec();
Some(packet)
Освен това не мисля, че е нужно да клонираш self.data
-- Packet::from_source
си очаква reference, взема назаем стойността на self.data
. Мисля, че можеше да подадеш директно &self.data
и щеше да сработи.
Тук и по-долу можеше да използваш оператора ?
за да избегнеш Err(x) => return Err(x)
:
let tuple: (Packet, &[u8]) = Packet::deserialize(packet_data)?;
deserialized.extend(tuple.0.payload);
let mut next_data = tuple.1;
И както казах по-горе, можеше и да pattern-match-неш компонентите на tuple.
Едно помощно средство, което аз написах за тестовете:
macro_rules! assert_match {
($expr:expr, $pat:pat) => {
if let $pat = $expr {
// all good
} else {
assert!(false, "Expression {:?} does not match the pattern {:?}", $expr, stringify!($pat));
}
}
}
По този начин, можеш да напишеш този тест по-просто така:
assert_match!(Packet::deserialize(&data), Err(PacketError::UnknownProtocolVersion));
И ако теста не проработи, ще получиш по-ясна грешка.
Добро решение, и ще ти дам бонус точка за обстойните тестове. Мисля си, че даже може би си написал повече тестове, отколкото си заслужава, но това е въпрос на интуиция, и обикновено повече тестове е по-добре от по-малко :).
Има някои езикови конструкции, с които би могъл да си съкратиш кода и вероятно да го направиш и по-четим -- хвърли им по едно око.
Няма нужда да използваш различно име -- можеше да е
let size = {
и тозиsize
да скрие оригиналната стойност. По този начин се подсигуряваш, че всякаква употреба наsize
надолу е правилния размер. Иначе има шанса някой да мешиreal_size
иsize
и потенциално да допусне тънък бъг.При нулев размер се очаква
InvalidPacket
, но това мисля, че вече го обсъдихме в discord.Вместо да вземаш
tuple
и после да достъпваш елементите сtuple.1
иtuple.0
(които не са много ясни имена), можеше да дефинираш две променливи с присвояването:Освен това не мисля, че е нужно да клонираш
self.data
--Packet::from_source
си очаква reference, взема назаем стойността наself.data
. Мисля, че можеше да подадеш директно&self.data
и щеше да сработи.Тук и по-долу можеше да използваш оператора
?
за да избегнешErr(x) => return Err(x)
:И както казах по-горе, можеше и да pattern-match-неш компонентите на tuple.
Едно помощно средство, което аз написах за тестовете:
По този начин, можеш да напишеш този тест по-просто така:
И ако теста не проработи, ще получиш по-ясна грешка.