Решение на Network Packets от Моника Киркова
Резултати
- 5 точки от тестове
- 0 бонус точки
- 5 точки общо
- 4 успешни тест(а)
- 11 неуспешни тест(а)
Код
Лог от изпълнението
Compiling solution v0.1.0 (/tmp/d20200111-2173579-1rnz1dw/solution)
warning: unused import: `std::convert::TryInto`
--> src/lib.rs:3:5
|
3 | use std::convert::TryInto;
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:89:11
|
89 | if(bytes.len() < 7 || (packet.size as usize) > packet.payload.len()){
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
|
= note: `#[warn(unused_parens)]` on by default
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:91:18
|
91 | }else if (packet.version != 1){
| ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:93:18
|
93 | }else if (packet.checksum != sumCheck){
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:95:17
|
95 | }else if((packet.size as usize) < packet.payload.len()){
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:115:11
|
115 | if(self.bytes.len() == 0){
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:143:15
|
143 | if(check.is_none()){
| ^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around assigned value
--> src/lib.rs:159:25
|
159 | let error = (Packet::deserialize(bytes));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around assigned value
--> src/lib.rs:169:27
|
169 | finalString = (finalString.to_owned() + (str::from_utf8(currPayload).unwrap()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unused variable: `a`
--> src/lib.rs:157:17
|
157 | let mut a = "";
| ^ help: consider prefixing with an underscore: `_a`
|
= note: `#[warn(unused_variables)]` on by default
warning: unused variable: `val`
--> src/lib.rs:162:20
|
162 | Ok(val)=>{
| ^^^ help: consider prefixing with an underscore: `_val`
warning: variable `sumCheck` is assigned to, but never used
--> src/lib.rs:165:21
|
165 | let mut sumCheck : u32 = 0;
| ^^^^^^^^
|
= note: consider using `_sumCheck` instead
warning: variable does not need to be mutable
--> src/lib.rs:46:13
|
46 | let mut packet = Packet {
| ----^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: variable does not need to be mutable
--> src/lib.rs:142:17
|
142 | let mut check = package.next();
| ----^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src/lib.rs:157:13
|
157 | let mut a = "";
| ----^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src/lib.rs:163:25
|
163 | let mut packet = &(Packet::deserialize(bytes)).unwrap().0;
| ----^^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src/lib.rs:164:17
|
164 | let mut currPayload = packet.payload;
| ----^^^^^^^^^^^
| |
| help: remove this `mut`
warning: variable `checkBytes` should have a snake case name
--> src/lib.rs:78:13
|
78 | let checkBytes: [u8; 4] = [check[0], check[1], check[2], check[3]];
| ^^^^^^^^^^ help: convert the identifier to snake case: `check_bytes`
|
= note: `#[warn(non_snake_case)]` on by default
warning: variable `sumCheck` should have a snake case name
--> src/lib.rs:85:17
|
85 | let mut sumCheck : u32 = 0;
| ^^^^^^^^ help: convert the identifier to snake case: `sum_check`
warning: variable `nextPacket` should have a snake case name
--> src/lib.rs:118:13
|
118 | let nextPacket = Packet::from_source(self.bytes, self.packet_size).0;
| ^^^^^^^^^^ help: convert the identifier to snake case: `next_packet`
warning: variable `vecOfBytes` should have a snake case name
--> src/lib.rs:140:17
|
140 | let mut vecOfBytes = Vec::new();
| ^^^^^^^^^^ help: convert the identifier to snake case: `vec_of_bytes`
warning: variable `finalString` should have a snake case name
--> src/lib.rs:156:17
|
156 | let mut finalString: std::string::String = "".to_string();
| ^^^^^^^^^^^ help: convert the identifier to snake case: `final_string`
warning: variable `currPayload` should have a snake case name
--> src/lib.rs:164:21
|
164 | let mut currPayload = packet.payload;
| ^^^^^^^^^^^ help: convert the identifier to snake case: `curr_payload`
warning: variable `sumCheck` should have a snake case name
--> src/lib.rs:165:21
|
165 | let mut sumCheck : u32 = 0;
| ^^^^^^^^ help: convert the identifier to snake case: `sum_check`
warning: unused import: `std::convert::TryInto`
--> src/lib.rs:3:5
|
3 | use std::convert::TryInto;
| ^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(unused_imports)]` on by default
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:89:11
|
89 | if(bytes.len() < 7 || (packet.size as usize) > packet.payload.len()){
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
|
= note: `#[warn(unused_parens)]` on by default
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:91:18
|
91 | }else if (packet.version != 1){
| ^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:93:18
|
93 | }else if (packet.checksum != sumCheck){
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:95:17
|
95 | }else if((packet.size as usize) < packet.payload.len()){
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:115:11
|
115 | if(self.bytes.len() == 0){
| ^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around `if` condition
--> src/lib.rs:143:15
|
143 | if(check.is_none()){
| ^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around assigned value
--> src/lib.rs:159:25
|
159 | let error = (Packet::deserialize(bytes));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unnecessary parentheses around assigned value
--> src/lib.rs:169:27
|
169 | finalString = (finalString.to_owned() + (str::from_utf8(currPayload).unwrap()));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove these parentheses
warning: unused variable: `a`
--> src/lib.rs:157:17
|
157 | let mut a = "";
| ^ help: consider prefixing with an underscore: `_a`
|
= note: `#[warn(unused_variables)]` on by default
warning: unused variable: `val`
--> src/lib.rs:162:20
|
162 | Ok(val)=>{
| ^^^ help: consider prefixing with an underscore: `_val`
warning: variable `sumCheck` is assigned to, but never used
--> src/lib.rs:165:21
|
165 | let mut sumCheck : u32 = 0;
| ^^^^^^^^
|
= note: consider using `_sumCheck` instead
warning: variable does not need to be mutable
--> src/lib.rs:46:13
|
46 | let mut packet = Packet {
| ----^^^^^^
| |
| help: remove this `mut`
|
= note: `#[warn(unused_mut)]` on by default
warning: variable does not need to be mutable
--> src/lib.rs:142:17
|
142 | let mut check = package.next();
| ----^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src/lib.rs:157:13
|
157 | let mut a = "";
| ----^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src/lib.rs:163:25
|
163 | let mut packet = &(Packet::deserialize(bytes)).unwrap().0;
| ----^^^^^^
| |
| help: remove this `mut`
warning: variable does not need to be mutable
--> src/lib.rs:164:17
|
164 | let mut currPayload = packet.payload;
| ----^^^^^^^^^^^
| |
| help: remove this `mut`
warning: variable `checkBytes` should have a snake case name
--> src/lib.rs:78:13
|
78 | let checkBytes: [u8; 4] = [check[0], check[1], check[2], check[3]];
| ^^^^^^^^^^ help: convert the identifier to snake case: `check_bytes`
|
= note: `#[warn(non_snake_case)]` on by default
warning: variable `sumCheck` should have a snake case name
--> src/lib.rs:85:17
|
85 | let mut sumCheck : u32 = 0;
| ^^^^^^^^ help: convert the identifier to snake case: `sum_check`
warning: variable `nextPacket` should have a snake case name
--> src/lib.rs:118:13
|
118 | let nextPacket = Packet::from_source(self.bytes, self.packet_size).0;
| ^^^^^^^^^^ help: convert the identifier to snake case: `next_packet`
warning: variable `vecOfBytes` should have a snake case name
--> src/lib.rs:140:17
|
140 | let mut vecOfBytes = Vec::new();
| ^^^^^^^^^^ help: convert the identifier to snake case: `vec_of_bytes`
warning: variable `finalString` should have a snake case name
--> src/lib.rs:156:17
|
156 | let mut finalString: std::string::String = "".to_string();
| ^^^^^^^^^^^ help: convert the identifier to snake case: `final_string`
warning: variable `currPayload` should have a snake case name
--> src/lib.rs:164:21
|
164 | let mut currPayload = packet.payload;
| ^^^^^^^^^^^ help: convert the identifier to snake case: `curr_payload`
warning: variable `sumCheck` should have a snake case name
--> src/lib.rs:165:21
|
165 | let mut sumCheck : u32 = 0;
| ^^^^^^^^ help: convert the identifier to snake case: `sum_check`
Finished test [unoptimized + debuginfo] target(s) in 3.76s
Running target/debug/deps/solution-a73e64ec87929bd0
running 0 tests
test result: ok. 0 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 ... FAILED
test solution_test::test_construct_packet_with_remainder ... ok
test solution_test::test_construct_packet_with_remainder_cyrillic ... FAILED
test solution_test::test_consuming_packets ... thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
FAILED
test solution_test::test_deserialize_invalid_packet ... FAILED
test solution_test::test_deserialize_packet ... FAILED
test solution_test::test_deserialize_unicode_packet ... FAILED
test solution_test::test_full_roundtrip ... thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
FAILED
test solution_test::test_full_roundtrip_for_zero_size_string ... ok
test solution_test::test_invalid_packet_combination ... thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
FAILED
test solution_test::test_iterating_packets ... thread '<unnamed>' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
FAILED
test solution_test::test_iterating_packets_for_zero_size_string ... ok
test solution_test::test_serialize_packet ... FAILED
test solution_test::test_zero_size ... FAILED
failures:
---- solution_test::test_construct_packet_no_remainder stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
---- solution_test::test_construct_packet_with_remainder_cyrillic stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
---- solution_test::test_consuming_packets stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:197:5
---- solution_test::test_deserialize_invalid_packet stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
---- solution_test::test_deserialize_packet stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
---- solution_test::test_deserialize_unicode_packet stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
---- solution_test::test_full_roundtrip stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:210:5
---- solution_test::test_invalid_packet_combination stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:232:5
---- solution_test::test_iterating_packets stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', tests/solution_test.rs:172:5
---- solution_test::test_serialize_packet stdout ----
thread 'main' panicked at 'called `Option::unwrap()` on a `None` value', src/libcore/option.rs:378:21
---- solution_test::test_zero_size stdout ----
note: test did not panic as expected
failures:
solution_test::test_construct_packet_no_remainder
solution_test::test_construct_packet_with_remainder_cyrillic
solution_test::test_consuming_packets
solution_test::test_deserialize_invalid_packet
solution_test::test_deserialize_packet
solution_test::test_deserialize_unicode_packet
solution_test::test_full_roundtrip
solution_test::test_invalid_packet_combination
solution_test::test_iterating_packets
solution_test::test_serialize_packet
solution_test::test_zero_size
test result: FAILED. 4 passed; 11 failed; 0 ignored; 0 measured; 0 filtered out
error: test failed, to rerun pass '--test solution_test'
История (2 версии и 4 коментара)
Моника качи решение на 03.12.2019 16:57 (преди почти 6 години)
use std::fmt;
use std::str;
use std::convert::TryInto;
#[derive(Debug)]
pub enum PacketError {
InvalidPacket,
InvalidChecksum,
UnknownProtocolVersion,
CorruptedMessage,
}
impl fmt::Display for PacketError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let err_msg = match self {
PacketError::InvalidPacket => "InvalidPacket",
PacketError::InvalidChecksum => "InvalidChecksum",
PacketError::UnknownProtocolVersion=>"UnknownProtocolVersion",
PacketError::CorruptedMessage=>"CorruptedMessage",
};
(write!(f, "{}", err_msg))
}
}
impl std::error::Error for PacketError {}
#[derive(PartialEq, Debug)]
pub struct Packet<'a> {
payload: &'a[u8],
checksum: u32,
version: u8,
size:u8,
}
impl<'a> Packet<'a> {
pub fn from_source(source: &'a [u8], size: u8) -> (Self, &[u8]) {
let n = size as usize;
let first = source.get(0..n).unwrap();
let second = source.get(n..source.len()).unwrap();
let mut checksum : u32 = 0;
for i in 0..first.len() {
checksum += *first.get(i).unwrap() as u32;
}
Доста C-подобен начин за итерация :). Вместо да итерираш по индекс, просто можеш да итерираш по елементите на колекцията: for byte in first { checksum += *byte as u32 } или нещо подобно. Същото се отнася за останалите цикли.
let mut packet = Packet {
payload: first,
version:1,
size: size,
checksum:checksum,
};
(packet, second)
}
pub fn payload(&self) -> &[u8] {
(&self.payload)
}
pub fn serialize(&self) -> Vec<u8>{
let slice = &self.payload();
let mut vec = Vec::new();
vec.push(*&self.version);
vec.push(*&self.size);
for i in 0..slice.len() {
vec.push(*slice.get(i).unwrap());
}
let check = &self.checksum.to_be_bytes();
for i in 0..4{
vec.push(check[i]);
}
(vec)
}
pub fn deserialize(bytes: &[u8]) -> Result<(Packet, &[u8]), PacketError>{
let pos = bytes[1] as usize;
let check = bytes.get(2+pos..6+pos).unwrap();
let checkBytes: [u8; 4] = [check[0], check[1], check[2], check[3]];
let packet = Packet {
version: bytes[0],
size: bytes[1],
payload: bytes.get(2..2+pos).unwrap(),
checksum: u32::from_be_bytes(checkBytes),
};
let mut sumCheck : u32 = 0;
for i in 0..packet.payload.len() {
sumCheck += *packet.payload.get(i).unwrap() as u32;
}
if(bytes.len() < 7 || (packet.size as usize) > packet.payload.len()){
Err(PacketError::InvalidPacket)
}else if (packet.version != 1){
Err(PacketError::UnknownProtocolVersion)
}else if (packet.checksum != sumCheck){
Err(PacketError::InvalidChecksum)
}else if((packet.size as usize) < packet.payload.len()){
Err(PacketError::InvalidChecksum)
}
else{
let exp = bytes.get(6+pos..bytes.len()).unwrap();
let pair = (packet, exp);
Ok(pair)
}
}
}
pub struct PacketSerializer<'a>{
packet_size: u8,
bytes: &'a[u8],
}
impl<'a> Iterator for PacketSerializer<'a> {
type Item = Packet<'a>;
fn next(& mut self) -> Option<Self::Item> {
if(self.bytes.len() == 0){
return None;
}
let nextPacket = Packet::from_source(self.bytes, self.packet_size).0;
self.bytes = Packet::from_source(self.bytes, self.packet_size).1;
Можеш да pattern-match-неш компонентите на един tuple:
let (nextPacket, bytes) = Packet::from_source(self.bytes, self.packet_size);
self.bytes = bytes;
Some(nextPacket)
(Some(nextPacket))
}
}
pub trait Packetable: Sized {
fn to_packets(&self, packet_size: u8) -> PacketSerializer;
fn to_packet_data(&self, packet_size: u8) -> Vec<u8>;
fn from_packet_data(packet_data: &[u8]) -> Result<Self, PacketError>;
}
impl Packetable for String {
fn to_packets(&self, packet_size: u8) -> PacketSerializer {
let p = PacketSerializer{
packet_size: packet_size,
bytes: self.as_bytes(),
};
(p)
}
fn to_packet_data(&self, packet_size: u8) -> Vec<u8> {
let mut package = self.to_packets(packet_size);
let mut vecOfBytes = Vec::new();
while package.bytes.len() > 0{
let mut check = package.next();
if(check.is_none()){
- println!("fdg");
- break;
+ return vecOfBytes;
}
let vec = (check.unwrap()).serialize();
for i in 0..vec.len(){
vecOfBytes.push(vec[i]);
}
}
Идеята PacketSerializer да бъде итератор е за да може да итерирате по него:
for packet in self.to_packets(packet_size) {
for byte in packet.serialize() {
vecOfBytes.push(byte);
}
}
Или нещо такова.
(vecOfBytes)
}
fn from_packet_data(packet_data: &[u8]) -> Result<Self, PacketError>{
let mut bytes = packet_data;
let mut finalString: std::string::String = "".to_string();
let mut a = "";
while bytes.len() > 0{
let error = (Packet::deserialize(bytes));
match error{
Err(e)=> return Err(e),
Ok(val)=>{
let mut packet = &(Packet::deserialize(bytes)).unwrap().0;
let mut currPayload = packet.payload;
let mut sumCheck : u32 = 0;
for i in 0..packet.payload.len() {
sumCheck += *packet.payload.get(i).unwrap() as u32;
}
finalString = (finalString.to_owned() + (str::from_utf8(currPayload).unwrap()));
bytes = (Packet::deserialize(bytes)).unwrap().1;
}
}
}
Ok(finalString.to_string())
}
}
Обещаващо начало на решение, но прибързано :). Късно си почнала, другия път си дай мноого повече време. Разгледай останалите решения, имаш доста логика, която е C-подобна и игнорира инструментите, които ти дава езика -- в Rust има по-лесни начини да решиш тези проблеми.

Доста C-подобен начин за итерация :). Вместо да итерираш по индекс, просто можеш да итерираш по елементите на колекцията:
for byte in first { checksum += *byte as u32 }или нещо подобно. Същото се отнася за останалите цикли.Можеш да pattern-match-неш компонентите на един tuple:
Идеята
PacketSerializerда бъде итератор е за да може да итерирате по него:Или нещо такова.