Skip to main content

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