Решение на Network Packets от Мирослав Лалев
Резултати
- 20 точки от тестове
- 1 бонус точка
- 21 точки общо
- 15 успешни тест(а)
- 0 неуспешни тест(а)
Код
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20200111-2173579-iiohcd/solution) Finished test [unoptimized + debuginfo] target(s) in 4.64s Running target/debug/deps/solution-a73e64ec87929bd0 running 9 tests test tests::packet_creation ... ok test tests::packet_creation_no_size ... ok test tests::packet_deserialize_errs ... ok test tests::packet_deserialize_returns_remainder ... ok test tests::packet_serialize_deserialize ... ok test tests::packet_serialize_deserialize_empty ... ok test tests::packet_serializer ... ok test tests::packetable_string ... ok test tests::packetable_string_corrupted ... ok test result: ok. 9 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 ... ok 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 test result: ok. 15 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out Doc-tests solution running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
История (2 версии и 6 коментара)
Мирослав качи решение на 01.12.2019 16:05 (преди почти 6 години)
Не бих използвал unreachable!
тук, понеже този случай със сигурност може да се reach-не -- просто трябва някой да го извика с 0 :). "Unreachable" ще рече "логически, не би трябвало да е възможно да се удари този случай". Примерно, ако в единия ръкав проверяваш n > 0
, а в другия n <= 0
, пак трябва да напишеш 3-ти ръкав със _
, който ще бъде наистина unreachable, но компилатора няма вградената логика да разбере това.
Алтернативно, и това би проработило: payload.iter().map(|item| *item as u32).sum()
. Твоя fold
е достатъчно разбираем, обаче, особено с името "sum" на променливата.
Хитро решение да използваш итератор за да се движиш напред по байтовете. Жалко само, че payload и checksum_bytes не се четат през итератора а се стига до 2 +
, 6 +
, etc. Но предполагам, че нещата са се усложнили с take-ването -- къде да ги съхраниш тия байтове, трябва да се направи вектор може би.
Аз използвах split_first
и split_at
за тия цели -- може да хвърлиш око на тия функции: https://doc.rust-lang.org/std/primitive.slice.html#method.split_at
Чудих се дали има начин да направя итераторът тук да работи върху референции (т.е. &Item
), което би ми позволило да напиша следното: .map(Packet::serialize)
?
Но пък дори и да може, ще трябва да се добави .copied
след .flatten
, така че май няма голямо значение.
Друг вариант е да направя serialize да взема оунършип, но тогава ще счупя апи-то.
Би могъл да опиташ type Item = &Packet
, за да може PacketSerializer
-а да връща references към пакети, но не съм много сигурен, че би било удобно. Пакетите вече са някакъв reference тип, да добавиш още едно ниво на индирекция ми изглежда като че би усложнило API-то ненужно (и да, би счупило тестовете, но ако искаш да експериментираш, може да си изтеглиш теста и да го модифицираш).
По принцип не бих променил интерфейса на кода само заради нещо такова. Да, би било по-красиво :). Но и това е достатъчно просто и ясно, и голяма промяна в интерфейса само заради малко подобрение в четимостта на този метод не си заслужава. Разбира се, заслужава си да мислиш и да експериментираш с тези неща -- пробвай!
Иначе, можеш да заместиш .map().flatten()
с .flat_map()
Добро решение и обстойни тестове, добра работа.
Не бих използвал
unreachable!
тук, понеже този случай със сигурност може да се reach-не -- просто трябва някой да го извика с 0 :). "Unreachable" ще рече "логически, не би трябвало да е възможно да се удари този случай". Примерно, ако в единия ръкав проверявашn > 0
, а в другияn <= 0
, пак трябва да напишеш 3-ти ръкав със_
, който ще бъде наистина unreachable, но компилатора няма вградената логика да разбере това.Алтернативно, и това би проработило:
payload.iter().map(|item| *item as u32).sum()
. Твояfold
е достатъчно разбираем, обаче, особено с името "sum" на променливата.Хитро решение да използваш итератор за да се движиш напред по байтовете. Жалко само, че payload и checksum_bytes не се четат през итератора а се стига до
2 +
,6 +
, etc. Но предполагам, че нещата са се усложнили с take-ването -- къде да ги съхраниш тия байтове, трябва да се направи вектор може би.Аз използвах
split_first
иsplit_at
за тия цели -- може да хвърлиш око на тия функции: https://doc.rust-lang.org/std/primitive.slice.html#method.split_atЧудих се дали има начин да направя итераторът тук да работи върху референции (т.е.
&Item
), което би ми позволило да напиша следното:.map(Packet::serialize)
?Но пък дори и да може, ще трябва да се добави
.copied
след.flatten
, така че май няма голямо значение.Друг вариант е да направя serialize да взема оунършип, но тогава ще счупя апи-то.
Би могъл да опиташ
type Item = &Packet
, за да можеPacketSerializer
-а да връща references към пакети, но не съм много сигурен, че би било удобно. Пакетите вече са някакъв reference тип, да добавиш още едно ниво на индирекция ми изглежда като че би усложнило API-то ненужно (и да, би счупило тестовете, но ако искаш да експериментираш, може да си изтеглиш теста и да го модифицираш).По принцип не бих променил интерфейса на кода само заради нещо такова. Да, би било по-красиво :). Но и това е достатъчно просто и ясно, и голяма промяна в интерфейса само заради малко подобрение в четимостта на този метод не си заслужава. Разбира се, заслужава си да мислиш и да експериментираш с тези неща -- пробвай!
Иначе, можеш да заместиш
.map().flatten()
с.flat_map()