1use anyhow::Result;
2use turbo_rcstr::{RcStr, rcstr};
3use turbo_tasks::{ResolvedVc, Vc};
4use turbo_tasks_fs::{
5 FileContent, FileJsonContent, FileLinesContent, FileSystemPath, LinkContent, LinkType,
6};
7
8use crate::version::{VersionedAssetContent, VersionedContent};
9
10#[turbo_tasks::value_trait]
12pub trait Asset {
13 #[turbo_tasks::function]
15 fn content(self: Vc<Self>) -> Vc<AssetContent>;
16
17 #[turbo_tasks::function]
19 fn versioned_content(self: Vc<Self>) -> Result<Vc<Box<dyn VersionedContent>>> {
20 Ok(Vc::upcast(VersionedAssetContent::new(self.content())))
21 }
22}
23
24#[turbo_tasks::value(shared)]
25#[derive(Clone)]
26pub enum AssetContent {
27 File(ResolvedVc<FileContent>),
28 Redirect { target: RcStr, link_type: LinkType },
32}
33
34#[turbo_tasks::value_impl]
35impl AssetContent {
36 #[turbo_tasks::function]
37 pub fn file(file: ResolvedVc<FileContent>) -> Result<Vc<Self>> {
38 Ok(AssetContent::File(file).cell())
39 }
40
41 #[turbo_tasks::function]
42 pub async fn parse_json(self: Vc<Self>) -> Result<Vc<FileJsonContent>> {
43 let this = self.await?;
44 match &*this {
45 AssetContent::File(content) => Ok(content.parse_json()),
46 AssetContent::Redirect { .. } => Ok(FileJsonContent::unparsable(rcstr!(
47 "a redirect can't be parsed as json"
48 ))
49 .cell()),
50 }
51 }
52
53 #[turbo_tasks::function]
54 pub async fn file_content(self: Vc<Self>) -> Result<Vc<FileContent>> {
55 let this = self.await?;
56 match &*this {
57 AssetContent::File(content) => Ok(**content),
58 AssetContent::Redirect { .. } => Ok(FileContent::NotFound.cell()),
59 }
60 }
61
62 #[turbo_tasks::function]
63 pub async fn lines(self: Vc<Self>) -> Result<Vc<FileLinesContent>> {
64 let this = self.await?;
65 match &*this {
66 AssetContent::File(content) => Ok(content.lines()),
67 AssetContent::Redirect { .. } => Ok(FileLinesContent::Unparsable.cell()),
68 }
69 }
70
71 #[turbo_tasks::function]
72 pub async fn len(self: Vc<Self>) -> Result<Vc<Option<u64>>> {
73 let this = self.await?;
74 match &*this {
75 AssetContent::File(content) => Ok(content.len()),
76 AssetContent::Redirect { .. } => Ok(Vc::cell(None)),
77 }
78 }
79
80 #[turbo_tasks::function]
81 pub async fn parse_json_with_comments(self: Vc<Self>) -> Result<Vc<FileJsonContent>> {
82 let this = self.await?;
83 match &*this {
84 AssetContent::File(content) => Ok(content.parse_json_with_comments()),
85 AssetContent::Redirect { .. } => Ok(FileJsonContent::unparsable(rcstr!(
86 "a redirect can't be parsed as json"
87 ))
88 .cell()),
89 }
90 }
91
92 #[turbo_tasks::function]
93 pub async fn write(self: Vc<Self>, path: FileSystemPath) -> Result<()> {
94 let this = self.await?;
95 match &*this {
96 AssetContent::File(file) => {
97 path.write(**file).as_side_effect().await?;
98 }
99 AssetContent::Redirect { target, link_type } => {
100 path.write_link(
101 LinkContent::Link {
102 target: target.clone(),
103 link_type: *link_type,
104 }
105 .cell(),
106 )
107 .as_side_effect()
108 .await?;
109 }
110 }
111 Ok(())
112 }
113}