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
122
123
124
125
126
127
mod error;
pub mod v1;
pub mod v2;
use std::pin::Pin;
use std::sync::Arc;
use futures::Future;
use serde::Deserialize;
use serde::Serialize;
use tokio::io::AsyncBufReadExt;
use tokio::io::AsyncReadExt;
use v2::ESZIP_V2_MAGIC;
pub use crate::error::ParseError;
pub use crate::v1::EszipV1;
pub use crate::v2::EszipV2;
pub use deno_ast;
pub use deno_graph;
pub enum Eszip {
V1(EszipV1),
V2(EszipV2),
}
type EszipParserFuture<R> =
Pin<Box<dyn Future<Output = Result<tokio::io::BufReader<R>, ParseError>>>>;
impl Eszip {
pub async fn parse<R: tokio::io::AsyncRead + Unpin + 'static>(
reader: R,
) -> Result<(Eszip, EszipParserFuture<R>), ParseError> {
let mut reader = tokio::io::BufReader::new(reader);
reader.fill_buf().await?;
let buffer = reader.buffer();
if buffer.len() >= 8 && &buffer[..8] == ESZIP_V2_MAGIC {
let (eszip, fut) = EszipV2::parse(reader).await?;
Ok((Eszip::V2(eszip), Box::pin(fut)))
} else {
let mut buffer = Vec::new();
reader.read_to_end(&mut buffer).await?;
let eszip = EszipV1::parse(&buffer)?;
let fut = async move { Ok::<_, ParseError>(reader) };
Ok((Eszip::V1(eszip), Box::pin(fut)))
}
}
pub fn get_module(&self, specifier: &str) -> Option<Module> {
match self {
Eszip::V1(eszip) => eszip.get_module(specifier),
Eszip::V2(eszip) => eszip.get_module(specifier),
}
}
}
pub struct Module {
pub specifier: String,
pub kind: ModuleKind,
inner: ModuleInner,
}
pub enum ModuleInner {
V1(Arc<Vec<u8>>),
V2(EszipV2),
}
impl Module {
pub async fn source(&self) -> Arc<Vec<u8>> {
match &self.inner {
ModuleInner::V1(source) => source.clone(),
ModuleInner::V2(eszip) => eszip.get_module_source(&self.specifier).await,
}
}
pub async fn source_map(&self) -> Option<Arc<Vec<u8>>> {
match &self.inner {
ModuleInner::V1(_) => None,
ModuleInner::V2(eszip) => {
Some(eszip.get_module_source_map(&self.specifier).await)
}
}
}
}
#[repr(u8)]
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum ModuleKind {
JavaScript = 0,
Json = 1,
}
#[cfg(test)]
mod tests {
use crate::Eszip;
#[tokio::test]
async fn parse_v1() {
let file = tokio::fs::File::open("./src/testdata/basic.json")
.await
.unwrap();
let (eszip, fut) = Eszip::parse(file).await.unwrap();
fut.await.unwrap();
assert!(matches!(eszip, Eszip::V1(_)));
eszip.get_module("https://gist.githubusercontent.com/lucacasonato/f3e21405322259ca4ed155722390fda2/raw/e25acb49b681e8e1da5a2a33744b7a36d538712d/hello.js").unwrap();
}
#[tokio::test]
async fn parse_v2() {
let file = tokio::fs::File::open("./src/testdata/redirect.eszip2")
.await
.unwrap();
let (eszip, fut) = Eszip::parse(file).await.unwrap();
fut.await.unwrap();
assert!(matches!(eszip, Eszip::V2(_)));
eszip.get_module("file:///main.ts").unwrap();
}
}