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
111
112
113
114
115
116
117
118
119
120
121
// Copyright (c) 2019 Parity Technologies (UK) Ltd.
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. All files in the project carrying such notice may not be copied,
// modified, or distributed except according to those terms.

//! Types describing various forms of payload data.

use std::{convert::TryFrom, fmt};

/// Data received from the remote end.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Incoming<'a> {
    /// Text or binary data.
    Data(Data),
    /// Data sent with a PONG control frame.
    Pong(&'a [u8])
}

impl Incoming<'_> {
    /// Is this text or binary data?
    pub fn is_data(&self) -> bool {
        if let Incoming::Data(_) = self { true } else { false }
    }

    /// Is this a PONG?
    pub fn is_pong(&self) -> bool {
        if let Incoming::Pong(_) = self { true } else { false }
    }

    /// Is this text data?
    pub fn is_text(&self) -> bool {
        if let Incoming::Data(d) = self {
            d.is_text()
        } else {
            false
        }
    }

    /// Is this binary data?
    pub fn is_binary(&self) -> bool {
        if let Incoming::Data(d) = self {
            d.is_binary()
        } else {
            false
        }
    }

    /// The length of data (number of bytes).
    pub fn len(&self) -> usize {
        match self {
            Incoming::Data(d) => d.len(),
            Incoming::Pong(d) => d.len()
        }
    }
}

#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Data {
    /// Textual data (number of bytes).
    Text(usize),
    /// Binary data (number of bytes).
    Binary(usize)
}

impl Data {
    /// Is this text data?
    pub fn is_text(&self) -> bool {
        if let Data::Text(_) = self { true } else { false }
    }

    /// Is this binary data?
    pub fn is_binary(&self) -> bool {
        if let Data::Binary(_) = self { true } else { false }
    }

    /// The length of data (number of bytes).
    pub fn len(&self) -> usize {
        match self {
            Data::Text(n) => *n,
            Data::Binary(n) => *n
        }
    }
}

/// Wrapper type which restricts the length of its byte slice to 125 bytes.
#[derive(Debug)]
pub struct ByteSlice125<'a>(&'a [u8]);

/// Error, if converting to [`ByteSlice125`] fails.
#[derive(Clone, Debug)]
pub struct SliceTooLarge(());

impl fmt::Display for SliceTooLarge {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.write_str("Slice larger than 125 bytes")
    }
}

impl std::error::Error for SliceTooLarge {}

impl<'a> TryFrom<&'a [u8]> for ByteSlice125<'a> {
    type Error = SliceTooLarge;

    fn try_from(value: &'a [u8]) -> Result<Self, Self::Error> {
        if value.len() > 125 {
            Err(SliceTooLarge(()))
        } else {
            Ok(ByteSlice125(value))
        }
    }
}

impl AsRef<[u8]> for ByteSlice125<'_> {
    fn as_ref(&self) -> &[u8] {
        self.0
    }
}