factory.rs 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. use crate::{innerlude::DynamicNode, AttributeValue, Element, LazyNodes, ScopeState, VNode};
  2. use bumpalo::boxed::Box as BumpBox;
  3. use bumpalo::Bump;
  4. use std::fmt::Arguments;
  5. use std::future::Future;
  6. #[doc(hidden)]
  7. pub trait ComponentReturn<'a, A = ()> {
  8. fn into_return(self, cx: &'a ScopeState) -> RenderReturn<'a>;
  9. }
  10. impl<'a> ComponentReturn<'a> for Element<'a> {
  11. fn into_return(self, _cx: &ScopeState) -> RenderReturn<'a> {
  12. RenderReturn::Sync(self)
  13. }
  14. }
  15. #[doc(hidden)]
  16. pub struct AsyncMarker;
  17. impl<'a, F> ComponentReturn<'a, AsyncMarker> for F
  18. where
  19. F: Future<Output = Element<'a>> + 'a,
  20. {
  21. fn into_return(self, cx: &'a ScopeState) -> RenderReturn<'a> {
  22. let f: &mut dyn Future<Output = Element<'a>> = cx.bump().alloc(self);
  23. RenderReturn::Async(unsafe { BumpBox::from_raw(f) })
  24. }
  25. }
  26. pub enum RenderReturn<'a> {
  27. /// A currently-available element
  28. Sync(Element<'a>),
  29. /// An ongoing future that will resolve to a [`Element`]
  30. Async(BumpBox<'a, dyn Future<Output = Element<'a>> + 'a>),
  31. }
  32. impl<'a> RenderReturn<'a> {
  33. pub(crate) unsafe fn extend_lifetime_ref<'c>(&self) -> &'c RenderReturn<'c> {
  34. unsafe { std::mem::transmute(self) }
  35. }
  36. pub(crate) unsafe fn extend_lifetime<'c>(self) -> RenderReturn<'c> {
  37. unsafe { std::mem::transmute(self) }
  38. }
  39. }
  40. #[doc(hidden)]
  41. pub trait IntoDynNode<'a, A = ()> {
  42. fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a>;
  43. }
  44. impl<'a> IntoDynNode<'a> for () {
  45. fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
  46. DynamicNode::placeholder()
  47. }
  48. }
  49. impl<'a> IntoDynNode<'a> for VNode<'a> {
  50. fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
  51. DynamicNode::Fragment(_cx.bump().alloc([self]))
  52. }
  53. }
  54. impl<'a> IntoDynNode<'a> for Element<'a> {
  55. fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
  56. match self {
  57. Ok(val) => val.into_vnode(_cx),
  58. _ => DynamicNode::placeholder(),
  59. }
  60. }
  61. }
  62. impl<'a, T: IntoDynNode<'a>> IntoDynNode<'a> for Option<T> {
  63. fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
  64. match self {
  65. Some(val) => val.into_vnode(_cx),
  66. None => DynamicNode::placeholder(),
  67. }
  68. }
  69. }
  70. impl<'a> IntoDynNode<'a> for &Element<'a> {
  71. fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
  72. match self.as_ref() {
  73. Ok(val) => val.clone().into_vnode(_cx),
  74. _ => DynamicNode::placeholder(),
  75. }
  76. }
  77. }
  78. impl<'a, 'b> IntoDynNode<'a> for LazyNodes<'a, 'b> {
  79. fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
  80. DynamicNode::Fragment(cx.bump().alloc([self.call(cx)]))
  81. }
  82. }
  83. impl<'a> IntoDynNode<'_> for &'a str {
  84. fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
  85. cx.text_node(format_args!("{}", self))
  86. }
  87. }
  88. impl IntoDynNode<'_> for String {
  89. fn into_vnode(self, cx: &ScopeState) -> DynamicNode {
  90. cx.text_node(format_args!("{}", self))
  91. }
  92. }
  93. impl<'b> IntoDynNode<'b> for Arguments<'_> {
  94. fn into_vnode(self, cx: &'b ScopeState) -> DynamicNode<'b> {
  95. cx.text_node(self)
  96. }
  97. }
  98. impl<'a> IntoDynNode<'a> for &'a VNode<'a> {
  99. fn into_vnode(self, _cx: &'a ScopeState) -> DynamicNode<'a> {
  100. DynamicNode::Fragment(_cx.bump().alloc([VNode {
  101. parent: self.parent,
  102. template: self.template,
  103. root_ids: self.root_ids,
  104. key: self.key,
  105. dynamic_nodes: self.dynamic_nodes,
  106. dynamic_attrs: self.dynamic_attrs,
  107. }]))
  108. }
  109. }
  110. pub trait IntoTemplate<'a> {
  111. fn into_template(self, _cx: &'a ScopeState) -> VNode<'a>;
  112. }
  113. impl<'a> IntoTemplate<'a> for VNode<'a> {
  114. fn into_template(self, _cx: &'a ScopeState) -> VNode<'a> {
  115. self
  116. }
  117. }
  118. impl<'a, 'b> IntoTemplate<'a> for LazyNodes<'a, 'b> {
  119. fn into_template(self, cx: &'a ScopeState) -> VNode<'a> {
  120. self.call(cx)
  121. }
  122. }
  123. // Note that we're using the E as a generic but this is never crafted anyways.
  124. #[doc(hidden)]
  125. pub struct FromNodeIterator;
  126. impl<'a, T, I> IntoDynNode<'a, FromNodeIterator> for T
  127. where
  128. T: Iterator<Item = I>,
  129. I: IntoTemplate<'a>,
  130. {
  131. fn into_vnode(self, cx: &'a ScopeState) -> DynamicNode<'a> {
  132. let mut nodes = bumpalo::collections::Vec::new_in(cx.bump());
  133. for node in self {
  134. nodes.push(node.into_template(cx));
  135. }
  136. let children = nodes.into_bump_slice();
  137. match children.len() {
  138. 0 => DynamicNode::placeholder(),
  139. _ => DynamicNode::Fragment(children),
  140. }
  141. }
  142. }
  143. /// A value that can be converted into an attribute value
  144. pub trait IntoAttributeValue<'a> {
  145. /// Convert into an attribute value
  146. fn into_value(self, bump: &'a Bump) -> AttributeValue<'a>;
  147. }
  148. impl<'a> IntoAttributeValue<'a> for &'a str {
  149. fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
  150. AttributeValue::Text(self)
  151. }
  152. }
  153. impl<'a> IntoAttributeValue<'a> for f32 {
  154. fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
  155. AttributeValue::Float(self)
  156. }
  157. }
  158. impl<'a> IntoAttributeValue<'a> for i32 {
  159. fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
  160. AttributeValue::Int(self)
  161. }
  162. }
  163. impl<'a> IntoAttributeValue<'a> for bool {
  164. fn into_value(self, _: &'a Bump) -> AttributeValue<'a> {
  165. AttributeValue::Bool(self)
  166. }
  167. }
  168. impl<'a> IntoAttributeValue<'a> for Arguments<'_> {
  169. fn into_value(self, bump: &'a Bump) -> AttributeValue<'a> {
  170. use bumpalo::core_alloc::fmt::Write;
  171. let mut str_buf = bumpalo::collections::String::new_in(bump);
  172. str_buf.write_fmt(self).unwrap();
  173. AttributeValue::Text(str_buf.into_bump_str())
  174. }
  175. }