turbopack_core/module_graph/
module_batch.rs

1use std::fmt::Debug;
2
3use anyhow::Result;
4use bincode::{Decode, Encode};
5use serde::{Deserialize, Serialize};
6use turbo_rcstr::RcStr;
7use turbo_tasks::{
8    NonLocalValue, ReadRef, ResolvedVc, TaskInput, TryJoinIterExt, ValueToString, Vc,
9    trace::TraceRawVcs,
10};
11
12use crate::{
13    chunk::ChunkableModule, module::Module, module_graph::chunk_group_info::RoaringBitmapWrapper,
14};
15
16#[derive(
17    Debug,
18    Copy,
19    Clone,
20    Hash,
21    PartialEq,
22    Eq,
23    Serialize,
24    Deserialize,
25    TraceRawVcs,
26    NonLocalValue,
27    TaskInput,
28    Encode,
29    Decode,
30)]
31pub enum ModuleOrBatch {
32    Module(ResolvedVc<Box<dyn Module>>),
33    Batch(ResolvedVc<ModuleBatch>),
34    None(usize),
35}
36
37impl ModuleOrBatch {
38    pub async fn ident_strings(self) -> Result<IdentStrings> {
39        Ok(match self {
40            ModuleOrBatch::Module(module) => {
41                IdentStrings::Single(module.ident().to_string().owned().await?)
42            }
43            ModuleOrBatch::Batch(batch) => IdentStrings::Multiple(batch.ident_strings().await?),
44            ModuleOrBatch::None(_) => IdentStrings::None,
45        })
46    }
47}
48
49#[derive(
50    Debug, Copy, Clone, Hash, PartialEq, Eq, TraceRawVcs, NonLocalValue, TaskInput, Encode, Decode,
51)]
52pub enum ChunkableModuleOrBatch {
53    Module(ResolvedVc<Box<dyn ChunkableModule>>),
54    Batch(ResolvedVc<ModuleBatch>),
55    None(usize),
56}
57
58impl ChunkableModuleOrBatch {
59    pub fn from_module_or_batch(module_or_batch: ModuleOrBatch) -> Option<Self> {
60        match module_or_batch {
61            ModuleOrBatch::Module(module) => ResolvedVc::try_downcast(module).map(Self::Module),
62            ModuleOrBatch::Batch(batch) => Some(Self::Batch(batch)),
63            ModuleOrBatch::None(i) => Some(Self::None(i)),
64        }
65    }
66
67    pub async fn ident_strings(self) -> Result<IdentStrings> {
68        Ok(match self {
69            ChunkableModuleOrBatch::Module(module) => {
70                IdentStrings::Single(module.ident().to_string().owned().await?)
71            }
72            ChunkableModuleOrBatch::Batch(batch) => {
73                IdentStrings::Multiple(batch.ident_strings().await?)
74            }
75            ChunkableModuleOrBatch::None(_) => IdentStrings::None,
76        })
77    }
78}
79
80impl From<ChunkableModuleOrBatch> for ModuleOrBatch {
81    fn from(chunkable_module_or_batch: ChunkableModuleOrBatch) -> Self {
82        match chunkable_module_or_batch {
83            ChunkableModuleOrBatch::Module(module) => Self::Module(ResolvedVc::upcast(module)),
84            ChunkableModuleOrBatch::Batch(batch) => Self::Batch(batch),
85            ChunkableModuleOrBatch::None(i) => Self::None(i),
86        }
87    }
88}
89
90pub enum IdentStrings {
91    None,
92    Single(RcStr),
93    Multiple(ReadRef<Vec<RcStr>>),
94}
95
96impl Debug for IdentStrings {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        match self {
99            IdentStrings::None => write!(f, "None"),
100            IdentStrings::Single(ident) => ident.fmt(f),
101            IdentStrings::Multiple(idents) => idents.fmt(f),
102        }
103    }
104}
105
106#[turbo_tasks::value]
107pub struct ModuleBatch {
108    pub modules: Vec<ResolvedVc<Box<dyn ChunkableModule>>>,
109    pub chunk_groups: Option<RoaringBitmapWrapper>,
110}
111
112#[turbo_tasks::value_impl]
113impl ModuleBatch {
114    #[turbo_tasks::function]
115    pub fn new(
116        modules: Vec<ResolvedVc<Box<dyn ChunkableModule>>>,
117        chunk_groups: Option<RoaringBitmapWrapper>,
118    ) -> Vc<Self> {
119        Self {
120            modules,
121            chunk_groups,
122        }
123        .cell()
124    }
125
126    #[turbo_tasks::function]
127    pub async fn ident_strings(&self) -> Result<Vc<Vec<RcStr>>> {
128        Ok(Vc::cell(
129            self.modules
130                .iter()
131                .map(|module| module.ident().to_string().owned())
132                .try_join()
133                .await?,
134        ))
135    }
136}
137
138#[turbo_tasks::value]
139pub struct ModuleBatchGroup {
140    pub items: Vec<ModuleOrBatch>,
141    pub chunk_groups: RoaringBitmapWrapper,
142}
143
144#[turbo_tasks::value_impl]
145impl ModuleBatchGroup {
146    #[turbo_tasks::function]
147    pub fn new(items: Vec<ModuleOrBatch>, chunk_groups: RoaringBitmapWrapper) -> Vc<Self> {
148        Self {
149            items,
150            chunk_groups,
151        }
152        .cell()
153    }
154}
155
156#[turbo_tasks::value]
157pub struct ChunkableModuleBatchGroup {
158    pub items: Vec<ChunkableModuleOrBatch>,
159    pub chunk_groups: RoaringBitmapWrapper,
160}
161
162#[turbo_tasks::value_impl]
163impl ChunkableModuleBatchGroup {
164    #[turbo_tasks::function]
165    pub async fn from_module_batch_group(batch_group: Vc<ModuleBatchGroup>) -> Result<Vc<Self>> {
166        let batch_group = batch_group.await?;
167        let items = batch_group
168            .items
169            .iter()
170            .filter_map(|batch| match *batch {
171                ModuleOrBatch::Module(module) => {
172                    ResolvedVc::try_downcast(module).map(ChunkableModuleOrBatch::Module)
173                }
174                ModuleOrBatch::Batch(batch) => Some(ChunkableModuleOrBatch::Batch(batch)),
175                ModuleOrBatch::None(_) => None,
176            })
177            .collect();
178        Ok(Self {
179            items,
180            chunk_groups: batch_group.chunk_groups.clone(),
181        }
182        .cell())
183    }
184}