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
use hyper::body::{Buf as _, Bytes};
use mlua::{Buffer as LuaBuffer, prelude::*};
/**
The inner data for a readable body.
*/
#[derive(Debug, Clone)]
pub enum ReadableBodyInner {
Bytes(Bytes),
String(String),
LuaString(LuaString),
LuaBuffer(LuaBuffer),
}
impl ReadableBodyInner {
pub fn len(&self) -> usize {
match self {
Self::Bytes(b) => b.len(),
Self::String(s) => s.len(),
Self::LuaString(s) => s.as_bytes().len(),
Self::LuaBuffer(b) => b.len(),
}
}
pub fn as_slice(&self) -> &[u8] {
/*
SAFETY: Reading lua strings and lua buffers as raw slices is safe while we can
guarantee that the inner Lua value + main lua struct has not yet been dropped
1. Buffers are fixed-size and guaranteed to never resize
2. We do not expose any method for writing to the body, only reading
3. We guarantee that net.request and net.serve futures are only driven forward
while we also know that the Lua + scheduler pair have not yet been dropped
4. Any writes from within lua to a buffer, are considered user error,
and are not unsafe, since the only possible outcome with the above
guarantees is invalid / mangled contents in request / response bodies
*/
match self {
Self::Bytes(b) => b.chunk(),
Self::String(s) => s.as_bytes(),
Self::LuaString(s) => unsafe {
// BorrowedBytes would not let us return a plain slice here,
// which is what the Buf implementation below needs - we need to
// do a little hack here to re-create the slice without a lifetime
let b = s.as_bytes();
let ptr = b.as_ptr();
let len = b.len();
std::slice::from_raw_parts(ptr, len)
},
Self::LuaBuffer(b) => unsafe {
// Similar to above, we need to get the raw slice for the buffer,
// which is a bit trickier here because Buffer has a read + write
// interface instead of using slices for some unknown reason
let v = LuaValue::Buffer(b.clone());
let ptr = v.to_pointer().cast::<u8>();
let len = b.len();
std::slice::from_raw_parts(ptr, len)
},
}
}
pub fn into_bytes(self) -> Bytes {
match self {
Self::Bytes(b) => b,
Self::String(s) => Bytes::from(s),
Self::LuaString(s) => Bytes::from(s.as_bytes().to_vec()),
Self::LuaBuffer(b) => Bytes::from(b.to_vec()),
}
}
}
impl From<&'static str> for ReadableBodyInner {
fn from(value: &'static str) -> Self {
Self::Bytes(Bytes::from(value))
}
}
impl From<Vec<u8>> for ReadableBodyInner {
fn from(value: Vec<u8>) -> Self {
Self::Bytes(Bytes::from(value))
}
}
impl From<Bytes> for ReadableBodyInner {
fn from(value: Bytes) -> Self {
Self::Bytes(value)
}
}
impl From<String> for ReadableBodyInner {
fn from(value: String) -> Self {
Self::String(value)
}
}
impl From<LuaString> for ReadableBodyInner {
fn from(value: LuaString) -> Self {
Self::LuaString(value)
}
}
impl From<LuaBuffer> for ReadableBodyInner {
fn from(value: LuaBuffer) -> Self {
Self::LuaBuffer(value)
}
}