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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//! Web messaging
use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};

use crate::serdes::{DumpError, Dumpable, LoadError, Loadable};
use crate::{RemoteCall, RemoteCallResponse};

/// Host IP address for web browsers
pub const HOST_STR: &str = "localhost";
/// Host IP address
pub const HOST: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1);

/// Standard max packet size
pub const PACKET_BUFFER_SIZE: usize = 1024;

/// Address and port
#[inline]
pub fn socket_addr(port: u16) -> SocketAddr {
    SocketAddr::V4(SocketAddrV4::new(HOST, port))
}

/// Accepted Packet types and the data they contain
pub enum Packet {
    /// A remote call
    Call(RemoteCall),
    /// A reponse to a remote call
    CallResponse(RemoteCallResponse),
    /// Unused
    KeepAlive,
    /// Invalid
    Invalid,
    /// General message
    Message(String),
    /// Response to an unsupported packet
    Unsupported,
    /// Broken packet type, useful for testing
    Bad,
    /// Many packets merged into one
    Many(Vec<Packet>),
}

impl Packet {
    /// Byte representing the packet type -- the first byte of any packet in USDPL
    const fn discriminant(&self) -> u8 {
        match self {
            Self::Call(_) => 1,
            Self::CallResponse(_) => 2,
            Self::KeepAlive => 3,
            Self::Invalid => 4,
            Self::Message(_) => 5,
            Self::Unsupported => 6,
            Self::Bad => 7,
            Self::Many(_) => 8,
        }
    }
}

impl Loadable for Packet {
    fn load(buf: &[u8]) -> Result<(Self, usize), LoadError> {
        if buf.len() == 0 {
            return Err(LoadError::TooSmallBuffer);
        }
        let mut result: (Self, usize) = match buf[0] {
            //0 => (None, 0),
            1 => {
                let (obj, len) = RemoteCall::load(&buf[1..])?;
                (Self::Call(obj), len)
            }
            2 => {
                let (obj, len) = RemoteCallResponse::load(&buf[1..])?;
                (Self::CallResponse(obj), len)
            }
            3 => (Self::KeepAlive, 0),
            4 => (Self::Invalid, 0),
            5 => {
                let (obj, len) = String::load(&buf[1..])?;
                (Self::Message(obj), len)
            }
            6 => (Self::Unsupported, 0),
            7 => return Err(LoadError::InvalidData),
            8 => {
                let (obj, len) = <_>::load(&buf[1..])?;
                (Self::Many(obj), len)
            }
            _ => return Err(LoadError::InvalidData),
        };
        result.1 += 1;
        Ok(result)
    }
}

impl Dumpable for Packet {
    fn dump(&self, buf: &mut [u8]) -> Result<usize, DumpError> {
        if buf.len() == 0 {
            return Err(DumpError::TooSmallBuffer);
        }
        buf[0] = self.discriminant();
        let mut result = match self {
            Self::Call(c) => c.dump(&mut buf[1..]),
            Self::CallResponse(c) => c.dump(&mut buf[1..]),
            Self::KeepAlive => Ok(0),
            Self::Invalid => Ok(0),
            Self::Message(s) => s.dump(&mut buf[1..]),
            Self::Unsupported => Ok(0),
            Self::Bad => return Err(DumpError::Unsupported),
            Self::Many(v) => v.dump(&mut buf[1..]),
        }?;
        result += 1;
        Ok(result)
    }
}