hotg_rune_proc_blocks/lib.rs
1//! Common abstractions used by all Rune proc blocks.
2//!
3//! # Feature Flags
4//!
5//! This crate has the following cargo feature flags:
6//!
7//! - `derive` - re-export the `#[derive(ProcBlock)]` from the
8//! `hotg-rune-proc-block-macros` crate
9
10#![no_std]
11#![cfg_attr(feature = "unstable_doc_cfg", feature(doc_cfg))]
12
13extern crate alloc;
14
15mod descriptor;
16
17pub use hotg_rune_core::Tensor;
18pub use descriptor::*;
19
20#[cfg(feature = "derive")]
21pub use hotg_rune_proc_block_macros::ProcBlock;
22
23/// This crate's version.
24pub const VERSION: &str = env!("CARGO_PKG_VERSION");
25
26/// Process some data, transforming it from one form to another.
27pub trait Transform<Input>: ProcBlock {
28 type Output;
29
30 fn transform(&mut self, input: Input) -> Self::Output;
31}
32
33/// The base trait that all proc blocks must implement.
34///
35/// This trait shouldn't be implemented manually, instead you should prefer the
36/// `#[derive(ProcBlock)]` custom derive.
37///
38/// # Struct Attributes
39///
40/// Use the `#[transform(...)]` attribute to specify which transformations are
41/// valid for a particular proc block. A plain primitive will be treated as a
42/// 1D `Tensor<T>`.
43///
44/// ```rust
45/// use hotg_rune_proc_blocks::{ProcBlock, Transform};
46/// use hotg_rune_core::Tensor;
47///
48/// #[derive(Default, hotg_rune_proc_block_macros::ProcBlock)]
49/// #[transform(inputs = f32, outputs = f32)]
50/// struct Foo { }
51///
52/// impl Transform<Tensor<f32>> for Foo {
53/// type Output = Tensor<f32>;
54/// fn transform(&mut self, _input: Tensor<f32>) -> Self::Output { todo!() }
55/// }
56/// ```
57///
58/// Forgetting to write the correct `Transform` implementation will fail to
59/// compile.
60///
61/// ```rust,compile_fail
62/// use hotg_rune_proc_blocks::{ProcBlock, Transform};
63/// use hotg_rune_core::Tensor;
64///
65/// #[derive(Default, hotg_rune_proc_block_macros::ProcBlock)] // Error: the trait bound `Foo: hotg_rune_proc_blocks::Transform<Tensor<f32>>` is not satisfied
66/// #[transform(inputs = f32, outputs = f32)]
67/// struct Foo { }
68///
69/// // impl Transform<Tensor<f32>> for Foo {
70/// // type Output = Tensor<f32>;
71/// // fn transform(&mut self, _input: Tensor<f32>) -> Self::Output { todo!() }
72/// // }
73/// ```
74///
75/// You can also specify the number of dimensions in an input or output. Using
76/// `_` indicates the transformation works with *any* number of dimensions.
77///
78/// ```rust
79/// use hotg_rune_proc_blocks::{ProcBlock, Transform};
80/// use hotg_rune_core::Tensor;
81/// use std::borrow::Cow;
82///
83/// #[derive(Default, hotg_rune_proc_block_macros::ProcBlock)]
84/// #[transform(inputs = [f32; _], outputs = [u8; 1920])]
85/// #[transform(inputs = utf8, outputs = [i16; 2])]
86/// struct Foo { }
87///
88/// impl Transform<Tensor<f32>> for Foo {
89/// type Output = Tensor<u8>;
90/// fn transform(&mut self, _input: Tensor<f32>) -> Self::Output { todo!() }
91/// }
92/// impl Transform<Tensor<Cow<'static, str>>> for Foo {
93/// type Output = Tensor<i16>;
94/// fn transform(&mut self, _input: Tensor<Cow<'static, str>>) -> Self::Output { todo!() }
95/// }
96/// ```
97///
98/// ## Field Attributes
99///
100/// By default, all fields in a proc block struct will be registered as
101/// "properties" and will get some generated setters. These setters accept a
102/// string and use [`core::str::FromStr`] to parse it into the correct type.
103///
104/// ```rust
105/// use hotg_rune_proc_blocks::ProcBlock;
106///
107/// #[derive(Default, hotg_rune_proc_block_macros::ProcBlock)]
108/// struct Foo {
109/// property: f64,
110/// }
111///
112/// let descriptor = Foo::DESCRIPTOR;
113///
114/// let mut foo = Foo::default();
115///
116/// foo.set_property("42").unwrap();
117/// assert_eq!(foo.property, 42.0);
118/// ```
119///
120/// A parameter can opt-out of this with the `#[proc_block(skip)]` attribute.
121///
122/// ```rust,compile_fail
123/// use hotg_rune_proc_blocks::ProcBlock;
124///
125/// #[derive(Default, hotg_rune_proc_block_macros::ProcBlock)]
126/// struct Foo {
127/// #[proc_block(skip)]
128/// skip_me: String,
129/// include_me: u32,
130/// }
131///
132/// let mut foo = Foo::default();
133///
134/// foo.set_skip_me("..."); // Error: no method named `set_skip_me` found for struct `Foo` in the current scope
135/// ```
136pub trait ProcBlock: Default + 'static {
137 /// A description of the proc block.
138 const DESCRIPTOR: ProcBlockDescriptor<'static>;
139}
140
141/// An internal module used by the `hotg_rune_proc_block_macros` crate
142/// so it has access to all the types it will need.
143#[doc(hidden)]
144pub mod internal {
145 pub use crate::{ProcBlock, Transform, descriptor::*};
146 pub use alloc::borrow::Cow;
147 pub use hotg_rune_core::{ElementType, Tensor};
148}