From fd417da04f7ca4b995de7f6510abafd3e9c31307 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Tue, 6 Jun 2023 21:13:59 +0200 Subject: Improve value casting infrastructure --- src/model/content.rs | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) (limited to 'src/model/content.rs') diff --git a/src/model/content.rs b/src/model/content.rs index f262d027..015f8b76 100644 --- a/src/model/content.rs +++ b/src/model/content.rs @@ -8,11 +8,11 @@ use ecow::{eco_format, EcoString, EcoVec}; use super::{ element, Behave, Behaviour, ElemFunc, Element, Fold, Guard, Label, Locatable, - Location, PlainText, Recipe, Selector, Style, Styles, Synthesize, + Location, Recipe, Selector, Style, Styles, Synthesize, }; use crate::diag::{SourceResult, StrResult}; use crate::doc::Meta; -use crate::eval::{Cast, Dict, Str, Value, Vm}; +use crate::eval::{Dict, FromValue, IntoValue, Str, Value, Vm}; use crate::syntax::Span; use crate::util::pretty_array_like; @@ -153,23 +153,24 @@ impl Content { pub fn with_field( mut self, name: impl Into, - value: impl Into, + value: impl IntoValue, ) -> Self { self.push_field(name, value); self } /// Attach a field to the content. - pub fn push_field(&mut self, name: impl Into, value: impl Into) { + pub fn push_field(&mut self, name: impl Into, value: impl IntoValue) { let name = name.into(); if let Some(i) = self.attrs.iter().position(|attr| match attr { Attr::Field(field) => *field == name, _ => false, }) { - self.attrs.make_mut()[i + 1] = Attr::Value(Prehashed::new(value.into())); + self.attrs.make_mut()[i + 1] = + Attr::Value(Prehashed::new(value.into_value())); } else { self.attrs.push(Attr::Field(name)); - self.attrs.push(Attr::Value(Prehashed::new(value.into()))); + self.attrs.push(Attr::Value(Prehashed::new(value.into_value()))); } } @@ -226,7 +227,7 @@ impl Content { } /// Try to access a field on the content as a specified type. - pub fn cast_field(&self, name: &str) -> Option { + pub fn cast_field(&self, name: &str) -> Option { match self.field(name) { Some(value) => value.cast().ok(), None => None, @@ -235,7 +236,7 @@ impl Content { /// Expect a field on the content to exist as a specified type. #[track_caller] - pub fn expect_field(&self, name: &str) -> T { + pub fn expect_field(&self, name: &str) -> T { self.field(name).unwrap().cast().unwrap() } @@ -311,12 +312,9 @@ impl Content { } } - /// Repeat this content `n` times. - pub fn repeat(&self, n: i64) -> StrResult { - let count = usize::try_from(n) - .map_err(|_| format!("cannot repeat this content {} times", n))?; - - Ok(Self::sequence(vec![self.clone(); count])) + /// Repeat this content `count` times. + pub fn repeat(&self, count: usize) -> Self { + Self::sequence(vec![self.clone(); count]) } /// Disable a show rule recipe. @@ -599,6 +597,12 @@ impl Fold for Vec { } } +/// Tries to extract the plain-text representation of the element. +pub trait PlainText { + /// Write this element's plain text into the given buffer. + fn plain_text(&self, text: &mut EcoString); +} + /// The missing key access error message when no default value was given. #[cold] fn missing_field_no_default(key: &str) -> EcoString { -- cgit v1.2.3