socketioxide_core/
lib.rs

1#![warn(
2    clippy::all,
3    clippy::todo,
4    clippy::empty_enum,
5    clippy::mem_forget,
6    clippy::unused_self,
7    clippy::filter_map_next,
8    clippy::needless_continue,
9    clippy::needless_borrow,
10    clippy::match_wildcard_for_single_variants,
11    clippy::if_let_mutex,
12    clippy::await_holding_lock,
13    clippy::match_on_vec_items,
14    clippy::imprecise_flops,
15    clippy::suboptimal_flops,
16    clippy::lossy_float_literal,
17    clippy::rest_pat_in_fully_bound_structs,
18    clippy::fn_params_excessive_bools,
19    clippy::exit,
20    clippy::inefficient_to_string,
21    clippy::linkedlist,
22    clippy::macro_use_imports,
23    clippy::option_option,
24    clippy::verbose_file_reads,
25    clippy::unnested_or_patterns,
26    rust_2018_idioms,
27    future_incompatible,
28    nonstandard_style,
29    missing_docs
30)]
31
32//! This crate is the core of the socketioxide crate.
33//! It contains basic types and interfaces for the socketioxide crate and the parser sub-crates.
34
35pub mod packet;
36pub mod parser;
37
38use std::collections::VecDeque;
39
40pub use engineioxide::{sid::Sid, Str};
41
42/// Represents a value that can be sent over the engine.io wire as an engine.io packet
43/// or the data that can be outputed by a binary parser (e.g. [`MsgPackParser`](../socketioxide_parser_msgpack/index.html))
44/// or a string parser (e.g. [`CommonParser`](../socketioxide_parser_common/index.html))).
45///
46/// If you want to deserialize this value to a specific type. You should manually call the `Data` extractor.
47#[derive(Debug, Clone, PartialEq)]
48pub enum Value {
49    /// A string payload that will be sent as a string engine.io packet.
50    /// It can also contain adjacent binary payloads.
51    Str(Str, Option<VecDeque<bytes::Bytes>>),
52    /// A binary payload that will be sent as a binary engine.io packet
53    Bytes(bytes::Bytes),
54}
55
56#[cfg(feature = "fuzzing")]
57impl arbitrary::Arbitrary<'_> for Value {
58    fn arbitrary(u: &mut arbitrary::Unstructured<'_>) -> arbitrary::Result<Self> {
59        let res = match u.arbitrary::<bool>()? {
60            true => Value::Bytes(u.arbitrary::<Vec<u8>>()?.into()),
61            false => Value::Str(
62                u.arbitrary::<String>()?.into(),
63                Some(
64                    u.arbitrary_iter::<Vec<u8>>()?
65                        .filter_map(|b| b.ok().map(bytes::Bytes::from))
66                        .collect(),
67                ),
68            ),
69        };
70        Ok(res)
71    }
72}
73
74impl Value {
75    /// Convert the value to a str slice if it can or return None
76    pub fn as_str(&self) -> Option<&Str> {
77        match self {
78            Value::Str(data, _) => Some(data),
79            Value::Bytes(_) => None,
80        }
81    }
82    /// Convert the value to a [`bytes::Bytes`] instance if it can or return None
83    pub fn as_bytes(&self) -> Option<&bytes::Bytes> {
84        match self {
85            Value::Str(_, _) => None,
86            Value::Bytes(data) => Some(data),
87        }
88    }
89    /// Get the length of the value
90    pub fn len(&self) -> usize {
91        match self {
92            Value::Str(data, _) => data.len(),
93            Value::Bytes(data) => data.len(),
94        }
95    }
96    /// Check if the value is empty
97    pub fn is_empty(&self) -> bool {
98        self.len() == 0
99    }
100}