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