#[path = "cbor.rs"]
mod cbor_;
#[path = "csv.rs"]
mod csv_;
#[path = "json.rs"]
mod json_;
#[path = "read.rs"]
mod read_;
#[path = "toml.rs"]
mod toml_;
#[path = "xml.rs"]
mod xml_;
#[path = "yaml.rs"]
mod yaml_;
use comemo::Tracked;
use ecow::EcoString;
use typst_syntax::{FileId, Spanned};
pub use self::cbor_::*;
pub use self::csv_::*;
pub use self::json_::*;
pub use self::read_::*;
pub use self::toml_::*;
pub use self::xml_::*;
pub use self::yaml_::*;
use crate::World;
use crate::diag::{At, SourceResult};
use crate::foundations::OneOrMultiple;
use crate::foundations::{Bytes, Scope, Str, cast};
pub(super) fn define(global: &mut Scope) {
global.start_category(crate::Category::DataLoading);
global.define_func::<read>();
global.define_func::<csv>();
global.define_func::<json>();
global.define_func::<toml>();
global.define_func::<yaml>();
global.define_func::<cbor>();
global.define_func::<xml>();
global.reset_category();
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum DataSource {
Path(EcoString),
Bytes(Bytes),
}
cast! {
DataSource,
self => match self {
Self::Path(v) => v.into_value(),
Self::Bytes(v) => v.into_value(),
},
v: EcoString => Self::Path(v),
v: Bytes => Self::Bytes(v),
}
pub trait Load {
type Output;
fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output>;
}
impl Load for Spanned<DataSource> {
type Output = Loaded;
fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
self.as_ref().load(world)
}
}
impl Load for Spanned<&DataSource> {
type Output = Loaded;
fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
match &self.v {
DataSource::Path(path) => {
let file_id = self.span.resolve_path(path).at(self.span)?;
let data = world.file(file_id).at(self.span)?;
let source = Spanned::new(LoadSource::Path(file_id), self.span);
Ok(Loaded::new(source, data))
}
DataSource::Bytes(data) => {
let source = Spanned::new(LoadSource::Bytes, self.span);
Ok(Loaded::new(source, data.clone()))
}
}
}
}
impl Load for Spanned<OneOrMultiple<DataSource>> {
type Output = Vec<Loaded>;
fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
self.as_ref().load(world)
}
}
impl Load for Spanned<&OneOrMultiple<DataSource>> {
type Output = Vec<Loaded>;
fn load(&self, world: Tracked<dyn World + '_>) -> SourceResult<Self::Output> {
self.v
.0
.iter()
.map(|source| Spanned::new(source, self.span).load(world))
.collect()
}
}
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Loaded {
pub source: Spanned<LoadSource>,
pub data: Bytes,
}
impl Loaded {
pub fn new(source: Spanned<LoadSource>, bytes: Bytes) -> Self {
Self { source, data: bytes }
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub enum LoadSource {
Path(FileId),
Bytes,
}
#[derive(Debug, Clone, PartialEq, Hash)]
pub enum Readable {
Str(Str),
Bytes(Bytes),
}
impl Readable {
pub fn into_bytes(self) -> Bytes {
match self {
Self::Bytes(v) => v,
Self::Str(v) => Bytes::from_string(v),
}
}
pub fn into_source(self) -> DataSource {
DataSource::Bytes(self.into_bytes())
}
}
cast! {
Readable,
self => match self {
Self::Str(v) => v.into_value(),
Self::Bytes(v) => v.into_value(),
},
v: Str => Self::Str(v),
v: Bytes => Self::Bytes(v),
}