1use std::future::Future;
2
3use anyhow::Result;
4use turbo_rcstr::RcStr;
5use turbo_tasks::Vc;
6pub use turbo_tasks_macros::ValueToString;
7
8use crate::{self as turbo_tasks};
9
10#[doc = include_str!("../FORMATTING.md")]
14#[turbo_tasks::value_trait]
15pub trait ValueToString {
16 #[turbo_tasks::function]
17 fn to_string(self: Vc<Self>) -> Vc<RcStr>;
18}
19
20pub trait ValueToStringRef {
23 fn to_string_ref(&self) -> impl Future<Output = Result<RcStr>> + Send;
24}
25
26impl<T: ValueToStringRef + Sync> ValueToStringRef for &T {
28 fn to_string_ref(&self) -> impl Future<Output = Result<RcStr>> + Send {
29 (**self).to_string_ref()
30 }
31}
32
33#[turbo_tasks::value_impl]
35impl ValueToString for RcStr {
36 #[turbo_tasks::function]
37 fn to_string(self: Vc<Self>) -> Vc<RcStr> {
38 self
39 }
40}
41
42impl ValueToStringRef for RcStr {
44 async fn to_string_ref(&self) -> Result<RcStr> {
45 Ok(self.clone())
46 }
47}
48
49impl<T> ValueToStringRef for crate::ReadRef<T>
51where
52 T: crate::VcValueType,
53 <T::Read as crate::VcRead<T>>::Target: ValueToStringRef,
54{
55 fn to_string_ref(&self) -> impl Future<Output = Result<RcStr>> + Send {
56 (**self).to_string_ref()
57 }
58}
59
60#[doc(hidden)]
62#[macro_export]
63macro_rules! __turbo_stringify {
64 ($name:ident, $i:expr) => {
65 let mut $name: $crate::display::macro_helpers::StringifyType = {
68 use $crate::display::macro_helpers::ValueToStringify as _;
69 let tmp = $crate::display::macro_helpers::ValueToStringifyWrap($i);
70 (&&&tmp).to_stringify().await?
71 };
72 };
73}
74
75#[doc(hidden)]
78pub mod macro_helpers {
79 use std::{
80 fmt::{self, Display},
81 future::Future,
82 };
83
84 use anyhow::Result;
85 use turbo_rcstr::RcStr;
86
87 use super::{ValueToString, ValueToStringRef};
88 use crate::vc::ResolvedVc;
89
90 pub struct ValueToStringifyWrap<T>(pub T);
91
92 pub trait ValueToStringify<const LEVEL: u8> {
93 fn to_stringify(&self) -> impl Future<Output = Result<StringifyType>> + Send;
94 }
95
96 pub enum StringifyType {
97 RcStr(RcStr),
98 String(String),
99 }
100
101 impl AsRef<str> for StringifyType {
102 fn as_ref(&self) -> &str {
103 match self {
104 StringifyType::RcStr(s) => s.as_str(),
105 StringifyType::String(s) => s.as_str(),
106 }
107 }
108 }
109
110 impl fmt::Debug for StringifyType {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 fmt::Debug::fmt(self.as_ref(), f)
113 }
114 }
115
116 impl Display for StringifyType {
117 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118 f.write_str(self.as_ref())
119 }
120 }
121
122 impl From<StringifyType> for RcStr {
123 fn from(s: StringifyType) -> Self {
124 match s {
125 StringifyType::RcStr(r) => r,
126 StringifyType::String(s) => RcStr::from(s),
127 }
128 }
129 }
130
131 impl<T: Display + Send + Sync> ValueToStringify<1> for &ValueToStringifyWrap<&T> {
133 #[inline(always)]
134 fn to_stringify(&self) -> impl Future<Output = Result<StringifyType>> + Send {
135 let s = (self.0).to_string();
136 async move { Ok(StringifyType::String(s)) }
137 }
138 }
139
140 impl<T: Send> ValueToStringify<2> for &&ValueToStringifyWrap<&crate::Vc<T>>
141 where
142 T: ValueToString,
143 {
144 #[inline(always)]
145 fn to_stringify(&self) -> impl Future<Output = Result<StringifyType>> + Send {
146 let vc = self.0;
147 async move {
148 let s = vc.to_string().await?;
149 Ok(StringifyType::RcStr((*s).clone()))
150 }
151 }
152 }
153
154 impl<T: Send> ValueToStringify<2> for &&ValueToStringifyWrap<&ResolvedVc<T>>
155 where
156 T: ValueToString,
157 {
158 #[inline(always)]
159 fn to_stringify(&self) -> impl Future<Output = Result<StringifyType>> + Send {
160 let vc = self.0;
161 async move {
162 let s = vc.to_string().await?;
163 Ok(StringifyType::RcStr((*s).clone()))
164 }
165 }
166 }
167
168 impl<T: Send> ValueToStringify<2> for &&&ValueToStringifyWrap<&T>
169 where
170 T: ValueToStringRef,
171 {
172 #[inline(always)]
173 fn to_stringify(&self) -> impl Future<Output = Result<StringifyType>> {
174 let s = self.0.to_string_ref();
175 async move { Ok(StringifyType::RcStr(s.await?)) }
176 }
177 }
178}