๐Ÿ“ฆ haasal / tftp-packet-rs

๐Ÿ“„ parsing.rs ยท 88 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88use std::str::from_utf8;

use nom::number::complete::be_u16;
use nom::{bytes::complete::*, IResult};

use crate::{ErrorCode, Mode, PacketError};

pub fn take_u16(input: &[u8]) -> IResult<&[u8], u16> {
    be_u16(input)
}

pub fn take_till_null(input: &[u8]) -> IResult<&[u8], &[u8]> {
    take_till(|c| c == 0)(input)
}

pub fn parse_filename(bytes: &[u8]) -> Result<(String, &[u8]), PacketError> {
    let (bytes, filename) = take_till_null(bytes)
        .map_err(|_| PacketError::InvalidPacket("Error while parsing filename".to_string()))?;

    let filename = from_utf8(filename)
        .map_err(|_| {
            PacketError::InvalidPacket(
                "Error while parsing filename. Not a valid UTF-8 string.".to_string(),
            )
        })?
        .to_string();

    Ok((filename, &bytes[1..]))
}

pub fn parse_mode(bytes: &[u8]) -> Result<(Mode, &[u8]), PacketError> {
    let (bytes, mode_bytes) = take_till_null(bytes)
        .map_err(|_| PacketError::InvalidPacket("Error while parsing mode".to_string()))?;

    let mode = from_utf8(mode_bytes).map_err(|_| {
        PacketError::InvalidPacket(
            "Error while parsing mode. Not a valid UTF-8 string.".to_string(),
        )
    })?;

    let mode: Mode = mode.try_into().map_err(|_| {
        PacketError::InvalidPacket("Error while parsing mode. Not a valid mode string.".to_string())
    })?;

    Ok((mode, bytes))
}

pub fn parse_block_number(bytes: &[u8]) -> Result<(u16, &[u8]), PacketError> {
    let (bytes, block_number) = take_u16(bytes).map_err(|_| {
        PacketError::InvalidPacket(
            "Error while parsing block number. Block number not a u16.".to_string(),
        )
    })?;

    Ok((block_number, bytes))
}

pub fn parse_error_code(bytes: &[u8]) -> Result<(ErrorCode, &[u8]), PacketError> {
    let (bytes, error_code) = take_u16(bytes).map_err(|_| {
        PacketError::InvalidPacket(
            "Error while parsing error code. Error code not a u16.".to_string(),
        )
    })?;

    let error_code = ErrorCode::try_from(error_code).map_err(|_| {
        PacketError::InvalidPacket(
            "Error while parsing error code. Error code not a valid error code.".to_string(),
        )
    })?;

    Ok((error_code, bytes))
}

pub fn parse_error_message(bytes: &[u8]) -> Result<(String, &[u8]), PacketError> {
    let (bytes, error_msg) = take_till_null(bytes)
        .map_err(|_| PacketError::InvalidPacket("Error while parsing error message".to_string()))?;

    let error_msg = from_utf8(error_msg)
        .map_err(|_| {
            PacketError::InvalidPacket(
                "Error while parsing error msg. Invalid UTF-8 string.".to_string(),
            )
        })?
        .to_string();

    Ok((error_msg, bytes))
}