New node: String Split (#3304)

* Add two nodes for substring

* fix: number convention

* Remove unnecessay allocations and add support for \n in patterns

* Make split node return Vec<String> and remove count_elements node

* Add Cache implementations for Vec<String>

* Code review

---------

Co-authored-by: daniil.loban <daniil.loban@gmail.com>
Co-authored-by: Dennis Kobert <dennis@kobert.dev>
Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Daniil Loban
2025-11-04 00:02:12 +03:00
committed by GitHub
parent c4bbb7e880
commit 0d8c521fbe
6 changed files with 54 additions and 3 deletions

View File

@@ -31,6 +31,7 @@ async fn context_modification<T>(
Context -> Vec<NodeId>,
Context -> Vec<f64>,
Context -> Vec<f32>,
Context -> Vec<String>,
Context -> Table<Vector>,
Context -> Table<Graphic>,
Context -> Table<Raster<CPU>>,

View File

@@ -451,6 +451,7 @@ fn index<T: AtIndex + Clone + Default>(
Vec<u32>,
Vec<u64>,
Vec<DVec2>,
Vec<String>,
Table<Artboard>,
Table<Graphic>,
Table<Vector>,

View File

@@ -69,6 +69,17 @@ fn string_length(_: impl Ctx, string: String) -> f64 {
string.chars().count() as f64
}
#[node_macro::node(category("Text"))]
fn string_split(_: impl Ctx, string: String, #[default("\\n")] delimeter: String, #[default(true)] delimeter_escaping: bool) -> Vec<String> {
let delimeter = if delimeter_escaping {
delimeter.replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t").replace("\\0", "\0").replace("\\\\", "\\")
} else {
delimeter
};
string.split(&delimeter).map(str::to_string).collect()
}
/// Evaluates either the "If True" or "If False" input branch based on whether the input condition is true or false.
#[node_macro::node(category("Math: Logic"))]
async fn switch<T, C: Send + 'n + Clone>(

View File

@@ -1954,11 +1954,39 @@ fn point_inside(_: impl Ctx, source: Table<Vector>, point: DVec2) -> bool {
source.into_iter().any(|row| row.element.check_point_inside_shape(row.transform, point))
}
trait Count {
fn count(&self) -> usize;
}
impl<T> Count for Table<T> {
fn count(&self) -> usize {
self.len()
}
}
impl<T> Count for Vec<T> {
fn count(&self) -> usize {
self.len()
}
}
// TODO: Return u32, u64, or usize instead of f64 after #1621 is resolved and has allowed us to implement automatic type conversion in the node graph for nodes with generic type inputs.
// TODO: (Currently automatic type conversion only works for concrete types, via the Graphene preprocessor and not the full Graphene type system.)
#[node_macro::node(category("General"), path(graphene_core::vector))]
async fn count_elements<I>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>, Table<Color>, Table<GradientStops>)] source: Table<I>) -> f64 {
source.len() as f64
async fn count_elements<I: Count>(
_: impl Ctx,
#[implementations(
Table<Graphic>,
Table<Vector>,
Table<Raster<CPU>>,
Table<Raster<GPU>>,
Table<Color>,
Table<GradientStops>,
Vec<String>,
Vec<f64>,
Vec<DVec2>,
)]
source: I,
) -> f64 {
source.count() as f64
}
#[node_macro::node(category("Vector: Measure"), path(graphene_core::vector))]