1use std::io::{Read, Write};
2
3use super::alert::*;
4use super::application_data::*;
5use super::change_cipher_spec::*;
6use super::handshake::*;
7use crate::error::*;
8
9#[derive(Default, Copy, Clone, PartialEq, Eq, Debug)]
15pub enum ContentType {
16 ChangeCipherSpec = 20,
17 Alert = 21,
18 Handshake = 22,
19 ApplicationData = 23,
20 #[default]
21 Invalid,
22}
23
24impl From<u8> for ContentType {
25 fn from(val: u8) -> Self {
26 match val {
27 20 => ContentType::ChangeCipherSpec,
28 21 => ContentType::Alert,
29 22 => ContentType::Handshake,
30 23 => ContentType::ApplicationData,
31 _ => ContentType::Invalid,
32 }
33 }
34}
35
36#[derive(PartialEq, Debug, Clone)]
37pub enum Content {
38 ChangeCipherSpec(ChangeCipherSpec),
39 Alert(Alert),
40 Handshake(Handshake),
41 ApplicationData(ApplicationData),
42}
43
44impl Content {
45 pub fn content_type(&self) -> ContentType {
46 match self {
47 Content::ChangeCipherSpec(c) => c.content_type(),
48 Content::Alert(c) => c.content_type(),
49 Content::Handshake(c) => c.content_type(),
50 Content::ApplicationData(c) => c.content_type(),
51 }
52 }
53
54 pub fn size(&self) -> usize {
55 match self {
56 Content::ChangeCipherSpec(c) => c.size(),
57 Content::Alert(c) => c.size(),
58 Content::Handshake(c) => c.size(),
59 Content::ApplicationData(c) => c.size(),
60 }
61 }
62
63 pub fn marshal<W: Write>(&self, writer: &mut W) -> Result<()> {
64 match self {
65 Content::ChangeCipherSpec(c) => c.marshal(writer),
66 Content::Alert(c) => c.marshal(writer),
67 Content::Handshake(c) => c.marshal(writer),
68 Content::ApplicationData(c) => c.marshal(writer),
69 }
70 }
71
72 pub fn unmarshal<R: Read>(content_type: ContentType, reader: &mut R) -> Result<Self> {
73 match content_type {
74 ContentType::ChangeCipherSpec => Ok(Content::ChangeCipherSpec(
75 ChangeCipherSpec::unmarshal(reader)?,
76 )),
77 ContentType::Alert => Ok(Content::Alert(Alert::unmarshal(reader)?)),
78 ContentType::Handshake => Ok(Content::Handshake(Handshake::unmarshal(reader)?)),
79 ContentType::ApplicationData => Ok(Content::ApplicationData(
80 ApplicationData::unmarshal(reader)?,
81 )),
82 _ => Err(Error::ErrInvalidContentType),
83 }
84 }
85}