typst_library/loading/
mod.rs1#[path = "cbor.rs"]
4mod cbor_;
5#[path = "csv.rs"]
6mod csv_;
7#[path = "json.rs"]
8mod json_;
9#[path = "read.rs"]
10mod read_;
11#[path = "toml.rs"]
12mod toml_;
13#[path = "xml.rs"]
14mod xml_;
15#[path = "yaml.rs"]
16mod yaml_;
17
18use comemo::Tracked;
19use ecow::EcoString;
20use typst_syntax::{FileId, Spanned};
21
22pub use self::cbor_::*;
23pub use self::csv_::*;
24pub use self::json_::*;
25pub use self::read_::*;
26pub use self::toml_::*;
27pub use self::xml_::*;
28pub use self::yaml_::*;
29
30use crate::World;
31use crate::diag::{At, SourceResult};
32use crate::foundations::OneOrMultiple;
33use crate::foundations::{Bytes, Scope, Str, cast};
34
35pub(super) fn define(global: &mut Scope) {
37 global.start_category(crate::Category::DataLoading);
38 global.define_func::<read>();
39 global.define_func::<csv>();
40 global.define_func::<json>();
41 global.define_func::<toml>();
42 global.define_func::<yaml>();
43 global.define_func::<cbor>();
44 global.define_func::<xml>();
45 global.reset_category();
46}
47
48#[derive(Debug, Clone, PartialEq, Hash)]
50pub enum DataSource {
51 Path(EcoString),
53 Bytes(Bytes),
55}
56
57cast! {
58 DataSource,
59 self => match self {
60 Self::Path(v) => v.into_value(),
61 Self::Bytes(v) => v.into_value(),
62 },
63 v: EcoString => Self::Path(v),
64 v: Bytes => Self::Bytes(v),
65}
66
67pub trait Load {
69 type Output;
71
72 fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output>;
74}
75
76impl Load for Spanned<DataSource> {
77 type Output = Loaded;
78
79 fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
80 self.as_ref().load(world)
81 }
82}
83
84impl Load for Spanned<&DataSource> {
85 type Output = Loaded;
86
87 fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
88 match &self.v {
89 DataSource::Path(path) => {
90 let file_id = self.span.resolve_path(path).at(self.span)?;
91 let data = world.file(file_id).at(self.span)?;
92 let source = Spanned::new(LoadSource::Path(file_id), self.span);
93 Ok(Loaded::new(source, data))
94 }
95 DataSource::Bytes(data) => {
96 let source = Spanned::new(LoadSource::Bytes, self.span);
97 Ok(Loaded::new(source, data.clone()))
98 }
99 }
100 }
101}
102
103impl Load for Spanned<OneOrMultiple<DataSource>> {
104 type Output = Vec<Loaded>;
105
106 fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
107 self.as_ref().load(world)
108 }
109}
110
111impl Load for Spanned<&OneOrMultiple<DataSource>> {
112 type Output = Vec<Loaded>;
113
114 fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
115 self.v
116 .0
117 .iter()
118 .map(|source| Spanned::new(source, self.span).load(world))
119 .collect()
120 }
121}
122
123#[derive(Debug, Clone, Eq, PartialEq, Hash)]
125pub struct Loaded {
126 pub source: Spanned<LoadSource>,
128 pub data: Bytes,
130}
131
132impl Loaded {
133 pub fn new(source: Spanned<LoadSource>, bytes: Bytes) -> Self {
134 Self { source, data: bytes }
135 }
136}
137
138#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
140pub enum LoadSource {
141 Path(FileId),
142 Bytes,
143}
144
145#[derive(Debug, Clone, PartialEq, Hash)]
147pub enum Readable {
148 Str(Str),
150 Bytes(Bytes),
152}
153
154impl Readable {
155 pub fn into_bytes(self) -> Bytes {
156 match self {
157 Self::Bytes(v) => v,
158 Self::Str(v) => Bytes::from_string(v),
159 }
160 }
161
162 pub fn into_source(self) -> DataSource {
163 DataSource::Bytes(self.into_bytes())
164 }
165}
166
167cast! {
168 Readable,
169 self => match self {
170 Self::Str(v) => v.into_value(),
171 Self::Bytes(v) => v.into_value(),
172 },
173 v: Str => Self::Str(v),
174 v: Bytes => Self::Bytes(v),
175}