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