Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement eager parsing, getting rid of lifetime on StyleSource #71

Merged
merged 2 commits into from
Apr 17, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# Changelog

## v0.11.0

### Breaking Changes:
- `StyleSource` does not take a lifetime argument
- Feature `parser`: `StyleSource` now eagerly parses its input.
- Feature `parser`: The conversion from `str` have been changed to `TryFrom`
instead of `From`. If you're using `yew`, the `IntoPropValue<StyleSource>`
impls still exist, but now panic early during conversion.

### Other Changes:
- The `Style::new_*` API is more open for accepted types of the `Css` parameter.

## v0.10.0

### Breaking Changes:
Expand Down
18 changes: 10 additions & 8 deletions examples/benchmarks/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -256,8 +256,9 @@ impl Component for Benchmarks {
}

impl YieldStyle for Benchmarks {
fn style_from(&self) -> StyleSource<'static> {
r#"
fn style_from(&self) -> StyleSource {
stylist::css!(
r#"
display: flex;
justify-content: center;
align-items: center;
Expand Down Expand Up @@ -300,8 +301,8 @@ impl YieldStyle for Benchmarks {
tbody tr:nth-child(even) {
background-color: rgb(240, 240, 240);
}
"#
.into()
"#
)
}
}

Expand Down Expand Up @@ -357,8 +358,9 @@ impl Component for App {
}

impl YieldStyle for App {
fn style_from(&self) -> StyleSource<'static> {
r#"
fn style_from(&self) -> StyleSource {
stylist::css!(
r#"
display: flex;
justify-content: center;
align-items: center;
Expand All @@ -373,8 +375,8 @@ impl YieldStyle for App {
height: 50px;
font-size: 20px;
}
"#
.into()
"#
)
}
}

Expand Down
9 changes: 5 additions & 4 deletions examples/yew-shadow/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,9 @@ impl Component for App {
}

impl YieldStyle for App {
fn style_from(&self) -> StyleSource<'static> {
r#"
fn style_from(&self) -> StyleSource {
stylist::css!(
r#"
box-shadow: 0 0 5px 1px rgba(0, 0, 0, 0.7);
height: 500px;
width: 500px;
Expand All @@ -133,8 +134,8 @@ impl YieldStyle for App {

flex-direction: column;
background-color: white;
"#
.into()
"#
)
}
}

Expand Down
6 changes: 6 additions & 0 deletions packages/stylist-core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ pub enum Error {
Web(Option<wasm_bindgen::JsValue>),
}

impl From<std::convert::Infallible> for Error {
fn from(infallible: std::convert::Infallible) -> Self {
match infallible {}
}
}

pub type Result<T> = std::result::Result<T, Error>;

pub trait ResultDisplay<T> {
Expand Down
21 changes: 10 additions & 11 deletions packages/stylist/src/global_style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ pub struct GlobalStyle {
impl GlobalStyle {
// The big method is monomorphic, so less code duplication and code bloat through generics
// and inlining
fn create_impl(css: StyleSource<'_>, manager: StyleManager) -> Result<Self> {
#[cfg(all(debug_assertions, feature = "parser"))]
use crate::ast::Sheet;

fn create_impl(css: StyleSource, manager: StyleManager) -> Result<Self> {
let prefix = format!("{}-global", manager.prefix());
let css = css.try_into_sheet()?;
let css = css.into_sheet();

// Creates the StyleKey, return from registry if already cached.
let key = StyleKey {
Expand All @@ -51,7 +48,7 @@ impl GlobalStyle {
// not corrupting the stylesheet.
#[cfg(all(debug_assertions, feature = "parser"))]
style_str
.parse::<Sheet>()
.parse::<crate::ast::Sheet>()
.expect_display("debug: Stylist failed to parse the style with interpolated values");

let new_style = Self {
Expand Down Expand Up @@ -83,21 +80,23 @@ impl GlobalStyle {
/// let style = Style::new("background-color: red;")?;
/// # Ok::<(), stylist::Error>(())
/// ```
pub fn new<'a, Css>(css: Css) -> Result<Self>
pub fn new<Css>(css: Css) -> Result<Self>
where
Css: Into<StyleSource<'a>>,
Css: TryInto<StyleSource>,
crate::Error: From<Css::Error>,
{
Self::new_with_manager(css, StyleManager::default())
}

/// Creates a new style using a custom manager.
pub fn new_with_manager<'a, Css, M>(css: Css, manager: M) -> Result<Self>
pub fn new_with_manager<Css, M>(css: Css, manager: M) -> Result<Self>
where
Css: Into<StyleSource<'a>>,
Css: TryInto<StyleSource>,
crate::Error: From<Css::Error>,
M: Into<StyleManager>,
{
let mgr = manager.into();
Self::create_impl(css.into(), mgr)
Self::create_impl(css.try_into()?, mgr)
}

/// Get the parsed and generated style in `&str`.
Expand Down
2 changes: 1 addition & 1 deletion packages/stylist/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
//! pub struct Component;
//!
//! impl YieldStyle for Component {
//! fn style_from(&self) -> StyleSource<'static> {
//! fn style_from(&self) -> StyleSource {
//! css!("color: red;")
//! }
//! }
Expand Down
35 changes: 18 additions & 17 deletions packages/stylist/src/style.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,13 +153,10 @@ impl Style {
// and inlining
fn create_impl(
class_prefix: Cow<'static, str>,
css: StyleSource<'_>,
css: StyleSource,
manager: StyleManager,
) -> Result<Self> {
#[cfg(all(debug_assertions, feature = "parser"))]
use crate::ast::Sheet;

let css = css.try_into_sheet()?;
let css = css.into_sheet();

// Creates the StyleKey, return from registry if already cached.
let key = StyleKey {
Expand All @@ -183,7 +180,7 @@ impl Style {
// not corrupting the stylesheet.
#[cfg(all(debug_assertions, feature = "parser"))]
style_str
.parse::<Sheet>()
.parse::<crate::ast::Sheet>()
.expect_display("debug: Stylist failed to parse the style with interpolated values");

let new_style = Self {
Expand Down Expand Up @@ -215,9 +212,10 @@ impl Style {
/// let style = Style::new("background-color: red;")?;
/// # Ok::<(), stylist::Error>(())
/// ```
pub fn new<'a, Css>(css: Css) -> Result<Self>
pub fn new<Css>(css: Css) -> Result<Self>
where
Css: Into<StyleSource<'a>>,
Css: TryInto<StyleSource>,
crate::Error: From<Css::Error>,
{
Self::create(StyleManager::default().prefix(), css)
}
Expand All @@ -232,34 +230,37 @@ impl Style {
/// let style = Style::create("my-component", "background-color: red;")?;
/// # Ok::<(), stylist::Error>(())
/// ```
pub fn create<'a, N, Css>(class_prefix: N, css: Css) -> Result<Self>
pub fn create<N, Css>(class_prefix: N, css: Css) -> Result<Self>
where
N: Into<Cow<'static, str>>,
Css: Into<StyleSource<'a>>,
Css: TryInto<StyleSource>,
crate::Error: From<Css::Error>,
{
Self::create_impl(class_prefix.into(), css.into(), StyleManager::default())
Self::create_with_manager(class_prefix, css, StyleManager::default())
}

/// Creates a new style from some parsable css with a default prefix using a custom
/// manager.
pub fn new_with_manager<'a, Css, M>(css: Css, manager: M) -> Result<Self>
pub fn new_with_manager<Css, M>(css: Css, manager: M) -> Result<Self>
where
Css: Into<StyleSource<'a>>,
Css: TryInto<StyleSource>,
crate::Error: From<Css::Error>,
M: Into<StyleManager>,
{
let mgr = manager.into();
Self::create_impl(mgr.prefix(), css.into(), mgr.clone())
Self::create_with_manager(mgr.prefix(), css, mgr.clone())
}

/// Creates a new style with a custom class prefix from some parsable css using a custom
/// manager.
pub fn create_with_manager<'a, N, Css, M>(class_prefix: N, css: Css, manager: M) -> Result<Self>
pub fn create_with_manager<N, Css, M>(class_prefix: N, css: Css, manager: M) -> Result<Self>
where
N: Into<Cow<'static, str>>,
Css: Into<StyleSource<'a>>,
Css: TryInto<StyleSource>,
crate::Error: From<Css::Error>,
M: Into<StyleManager>,
{
Self::create_impl(class_prefix.into(), css.into(), manager.into())
Self::create_impl(class_prefix.into(), css.try_into()?, manager.into())
}

/// Returns the class name for current style
Expand Down
73 changes: 29 additions & 44 deletions packages/stylist/src/style_src.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,11 @@
#[cfg(feature = "parser")]
use std::borrow::Cow;
#[cfg(not(feature = "parser"))]
use std::marker::PhantomData;

use crate::ast::Sheet;
use crate::manager::StyleManager;
use crate::Result;
#[cfg(feature = "yew")]
use crate::Style;

#[cfg(feature = "parser")]
#[derive(Debug, Clone, PartialEq)]
enum SheetSource<'a> {
String(Cow<'a, str>),
Sheet(Sheet),
}

#[cfg(not(feature = "parser"))]
#[derive(Debug, Clone, PartialEq)]
enum SheetSource {
Sheet(Sheet),
Expand All @@ -30,31 +19,25 @@ enum SheetSource {
/// You can also get a StyleSource instance from a string or a [`Sheet`] by calling `.into()`.
///
/// ```rust
/// use stylist::StyleSource;
/// use yew::prelude::*;
/// use stylist::yew::Global;
/// use stylist::{css, StyleSource, yew::Global};
///
/// let s: StyleSource = "color: red;".into();
/// let s: StyleSource = css!("color: red;");
///
/// let rendered = html! {<div class={s.clone()} />};
/// let global_rendered = html! {<Global css={s} />};
/// ```
#[derive(Debug, Clone, PartialEq)]
pub struct StyleSource<'a> {
pub struct StyleSource {
#[cfg(feature = "parser")]
inner: SheetSource<'a>,

#[cfg(not(feature = "parser"))]
inner: SheetSource,
WorldSEnder marked this conversation as resolved.
Show resolved Hide resolved
#[cfg(not(feature = "parser"))]
_marker: PhantomData<&'a ()>,

manager: Option<StyleManager>,
#[cfg(all(debug_assertions, feature = "debug_style_locations"))]
pub(crate) location: String,
}

impl StyleSource<'_> {
impl StyleSource {
#[cfg(all(debug_assertions, feature = "debug_style_locations"))]
#[track_caller]
pub(crate) fn get_caller_location() -> String {
Expand All @@ -68,11 +51,9 @@ impl StyleSource<'_> {
)
}

pub(crate) fn try_into_sheet(self) -> Result<Sheet> {
pub(crate) fn into_sheet(self) -> Sheet {
match self.inner {
SheetSource::Sheet(m) => Ok(m),
#[cfg(feature = "parser")]
SheetSource::String(m) => Ok(m.parse::<Sheet>()?),
SheetSource::Sheet(m) => m,
}
}

Expand All @@ -91,13 +72,11 @@ impl StyleSource<'_> {
}
}

impl From<Sheet> for StyleSource<'_> {
impl From<Sheet> for StyleSource {
#[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)]
fn from(other: Sheet) -> StyleSource<'static> {
fn from(other: Sheet) -> StyleSource {
StyleSource {
inner: SheetSource::Sheet(other),
#[cfg(not(feature = "parser"))]
_marker: PhantomData,
manager: None,
#[cfg(all(debug_assertions, feature = "debug_style_locations"))]
location: Self::get_caller_location(),
Expand All @@ -110,39 +89,45 @@ impl From<Sheet> for StyleSource<'_> {
mod feat_parser {
use super::*;

impl From<String> for StyleSource<'_> {
impl TryFrom<String> for StyleSource {
type Error = crate::Error;
#[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)]
fn from(other: String) -> StyleSource<'static> {
StyleSource {
inner: SheetSource::String(other.into()),
fn try_from(other: String) -> crate::Result<StyleSource> {
let sheet = SheetSource::Sheet(other.parse()?);
Ok(StyleSource {
inner: sheet,
manager: None,
#[cfg(all(debug_assertions, feature = "debug_style_locations"))]
location: Self::get_caller_location(),
}
})
}
}

impl<'a> From<&'a str> for StyleSource<'a> {
impl<'a> TryFrom<&'a str> for StyleSource {
WorldSEnder marked this conversation as resolved.
Show resolved Hide resolved
type Error = crate::Error;
#[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)]
fn from(other: &'a str) -> StyleSource<'a> {
StyleSource {
inner: SheetSource::String(other.into()),
fn try_from(other: &'a str) -> crate::Result<StyleSource> {
let sheet = SheetSource::Sheet(other.parse()?);
Ok(StyleSource {
inner: sheet,
manager: None,
#[cfg(all(debug_assertions, feature = "debug_style_locations"))]
location: Self::get_caller_location(),
}
})
}
}

impl<'a> From<Cow<'a, str>> for StyleSource<'a> {
impl<'a> TryFrom<Cow<'a, str>> for StyleSource {
type Error = crate::Error;
#[cfg_attr(all(debug_assertions, feature = "debug_style_locations"), track_caller)]
fn from(other: Cow<'a, str>) -> StyleSource<'a> {
StyleSource {
inner: SheetSource::String(other),
fn try_from(other: Cow<'a, str>) -> crate::Result<StyleSource> {
let sheet = SheetSource::Sheet(other.parse()?);
Ok(StyleSource {
inner: sheet,
manager: None,
#[cfg(all(debug_assertions, feature = "debug_style_locations"))]
location: Self::get_caller_location(),
}
})
}
}
}
Loading