use futures_util::FutureExt;
pub use futures_util::{
future::{Either, try_join_all},
try_join,
};
use topcoat_core::{context::Cx, error::Result};
pub use crate::buffer::ViewSlot;
use crate::{
Attribute, AttributeKeyViewParts, AttributeValueViewParts, AttributeViewParts,
ElementNameViewParts, HtmlContext, NodeViewParts, PartsWriter, Unescaped, View,
buffer::{ViewBuffer, ViewBufferScope},
};
pub fn build(fut: impl Future<Output = Result<View>>) -> impl Future<Output = Result<View>> {
ViewBufferScope::scope(fut).map(|(view, buffer)| Ok(view?.seal(buffer)))
}
pub fn build_sync(f: impl FnOnce() -> View) -> View {
let (view, buffer) = ViewBufferScope::scope_sync(f);
view.seal(buffer)
}
pub fn block(cx: &Cx, f: impl FnOnce(&mut Builder<'_, '_, '_>)) -> View {
write_block(|parts| f(&mut Builder { cx, parts }))
}
pub fn write_block(f: impl FnOnce(&mut PartsWriter<'_>)) -> View {
ViewBufferScope::with(|buffer| PartsWriter::block(buffer, f))
}
#[must_use]
pub fn reserve() -> (View, ViewSlot) {
ViewBufferScope::with(ViewBuffer::reserve_view)
}
pub fn ready(view: View) -> futures_util::future::Ready<Result<View>> {
futures_util::future::ready(Ok(view))
}
#[inline]
pub fn in_context<R>(
parts: &mut PartsWriter<'_>,
context: HtmlContext,
f: impl FnOnce(&mut PartsWriter<'_>) -> R,
) -> R {
parts.in_context(context, f)
}
#[inline]
pub fn view(parts: &mut PartsWriter<'_>, view: View) {
parts.push_view(view);
}
pub struct Builder<'a, 'b, 'c> {
cx: &'a Cx,
parts: &'b mut PartsWriter<'c>,
}
impl Builder<'_, '_, '_> {
#[inline]
pub fn markup(&mut self, s: &'static &'static str) {
self.parts.push_promoted_str_unescaped(s);
}
#[inline]
pub fn node(&mut self, value: impl NodeViewParts) {
let cx = self.cx;
self.parts.in_context(HtmlContext::Text, |parts| {
value.into_view_parts(cx, parts);
});
}
#[inline]
pub fn element_name(&mut self, value: impl ElementNameViewParts) {
let cx = self.cx;
self.parts.in_context(HtmlContext::ElementName, |parts| {
value.into_view_parts(cx, parts);
});
}
#[inline]
pub fn attribute_key(&mut self, value: impl AttributeKeyViewParts) {
let cx = self.cx;
self.parts.in_context(HtmlContext::AttributeKey, |parts| {
value.into_view_parts(cx, parts);
});
}
#[inline]
pub fn attribute_value(&mut self, value: impl AttributeValueViewParts) {
let cx = self.cx;
self.parts.in_context(HtmlContext::AttributeValue, |parts| {
value.into_view_parts(cx, parts);
});
}
#[inline]
pub fn attribute(
&mut self,
(key, value): (impl AttributeKeyViewParts, impl AttributeValueViewParts),
) {
self.attributes(Attribute::new(key, value));
}
#[inline]
pub fn attribute_unescaped(
&mut self,
(key, value): (&'static str, impl AttributeValueViewParts),
) {
self.attributes(Attribute::new(Unescaped::new_unchecked(key), value));
}
#[inline]
pub fn attributes(&mut self, attributes: impl AttributeViewParts) {
let cx = self.cx;
self.parts.in_context(HtmlContext::AttributeValue, |parts| {
attributes.into_view_parts(cx, parts);
});
}
#[inline]
pub fn view(&mut self, view: View) {
self.parts.push_view(view);
}
}