WIP: image processing library (or libraries?) #12
7 changed files with 48 additions and 43 deletions
|
@ -2,7 +2,8 @@
|
|||
members = [
|
||||
"crates/app",
|
||||
"crates/eval",
|
||||
"crates/ir", "crates/prowocessing",
|
||||
"crates/ir",
|
||||
"crates/prowocessing",
|
||||
]
|
||||
resolver = "2"
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ enum Commands {
|
|||
},
|
||||
Dev {
|
||||
#[command(subcommand)]
|
||||
dev_command: DevCommands,
|
||||
command: DevCommands,
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,9 @@ fn main() {
|
|||
machine.feed(ir);
|
||||
machine.eval_full();
|
||||
}
|
||||
Commands::Dev { dev_command } => dev_command.run(),
|
||||
Commands::Dev {
|
||||
command: dev_command,
|
||||
} => dev_command.run(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
//! Definitions of the data transfer and storage types.
|
||||
|
||||
/// Types for element and pipeline IO
|
||||
pub mod io;
|
||||
|
||||
/// Raw data types contained in `io`
|
||||
pub mod raw;
|
||||
|
|
|
@ -1,22 +1,26 @@
|
|||
use super::raw::{Data, OwnedData};
|
||||
//! Types for element and pipeline IO
|
||||
|
||||
use std::convert::Into;
|
||||
|
||||
use super::raw::{Data, DataRef};
|
||||
|
||||
/// Newtype struct with borrowed types for pipeline/element inputs, so that doesn't force a move or clone
|
||||
schrottkatze marked this conversation as resolved
|
||||
pub struct Inputs<'a>(Vec<Data<'a>>);
|
||||
pub struct Inputs<'a>(Vec<DataRef<'a>>);
|
||||
|
||||
impl<'a> Inputs<'a> {
|
||||
/// get inner value(s)
|
||||
pub(crate) fn inner(&self) -> Vec<Data<'a>> {
|
||||
pub(crate) fn inner(&self) -> Vec<DataRef<'a>> {
|
||||
self.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<Vec<Data<'a>>> for Inputs<'a> {
|
||||
fn from(value: Vec<Data<'a>>) -> Self {
|
||||
impl<'a> From<Vec<DataRef<'a>>> for Inputs<'a> {
|
||||
fn from(value: Vec<DataRef<'a>>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Into<Data<'a>>> From<T> for Inputs<'a> {
|
||||
impl<'a, T: Into<DataRef<'a>>> From<T> for Inputs<'a> {
|
||||
fn from(value: T) -> Self {
|
||||
Self(vec![value.into()])
|
||||
}
|
||||
|
@ -24,25 +28,25 @@ impl<'a, T: Into<Data<'a>>> From<T> for Inputs<'a> {
|
|||
|
||||
impl<'a> From<&'a Outputs> for Inputs<'a> {
|
||||
fn from(value: &'a Outputs) -> Self {
|
||||
Self(value.0.iter().map(std::convert::Into::into).collect())
|
||||
Self(value.0.iter().map(Into::into).collect())
|
||||
}
|
||||
}
|
||||
|
||||
/// Newtype struct around `OwnedData` for pipeline/element outputs
|
||||
pub struct Outputs(Vec<OwnedData>);
|
||||
/// Used for pipeline/element outputs
|
||||
pub struct Outputs(Vec<Data>);
|
||||
schrottkatze marked this conversation as resolved
multisamplednight
commented
Wait, why is Wait, why is `Outputs` allowed to be consumed for its inner content consumed while `Inputs` doesn't?
schrottkatze
commented
(I'm currently not happy how the IO of instructions works anyway, planning on reworking that to be more sensible, clear and flexible)) `Inputs` only contains a `Vec` of `Data` which either contains a string slice or an integer, which are really cheap to clone. `OwnedData` would be much heavier to clone in this case.
(I'm currently not happy how the IO of instructions works anyway, planning on reworking that to be more sensible, clear and flexible))
|
||||
|
||||
impl Outputs {
|
||||
/// consume self and return inner value(s)
|
||||
pub fn into_inner(self) -> Vec<OwnedData> {
|
||||
pub fn into_inner(self) -> Vec<Data> {
|
||||
self.0
|
||||
}
|
||||
}
|
||||
impl From<Vec<OwnedData>> for Outputs {
|
||||
fn from(value: Vec<OwnedData>) -> Self {
|
||||
impl From<Vec<Data>> for Outputs {
|
||||
fn from(value: Vec<Data>) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
impl<T: Into<OwnedData>> From<T> for Outputs {
|
||||
impl<T: Into<Data>> From<T> for Outputs {
|
||||
fn from(value: T) -> Self {
|
||||
Self(vec![value.into()])
|
||||
}
|
||||
|
@ -53,7 +57,7 @@ impl From<Inputs<'_>> for Outputs {
|
|||
value
|
||||
.0
|
||||
.into_iter()
|
||||
.map(|i: Data<'_>| Data::to_owned_data(&i))
|
||||
.map(|i: DataRef<'_>| DataRef::to_owned_data(&i))
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,58 +1,58 @@
|
|||
//! Dynamic data storage and transfer types
|
||||
//! Dynamic data storage and transfer types for use in [`io`]
|
||||
|
||||
/// Owned data type, for use mostly in outputs and storage
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OwnedData {
|
||||
pub enum Data {
|
||||
String(String),
|
||||
Int(i32),
|
||||
}
|
||||
|
||||
impl From<String> for OwnedData {
|
||||
impl From<String> for Data {
|
||||
fn from(value: String) -> Self {
|
||||
Self::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for OwnedData {
|
||||
impl From<i32> for Data {
|
||||
fn from(value: i32) -> Self {
|
||||
Self::Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unowned data type, for inputs into runner functions
|
||||
#[derive(Clone, Copy)]
|
||||
pub enum Data<'a> {
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub enum DataRef<'a> {
|
||||
String(&'a str),
|
||||
Int(i32),
|
||||
}
|
||||
|
||||
impl Data<'_> {
|
||||
impl DataRef<'_> {
|
||||
/// converts itself to `OwnedData`
|
||||
pub fn to_owned_data(&self) -> OwnedData {
|
||||
pub fn to_owned_data(&self) -> Data {
|
||||
match self {
|
||||
Data::String(s) => (*s).to_owned().into(),
|
||||
Data::Int(i) => (*i).into(),
|
||||
DataRef::String(s) => (*s).to_owned().into(),
|
||||
DataRef::Int(i) => (*i).into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for Data<'a> {
|
||||
impl<'a> From<&'a str> for DataRef<'a> {
|
||||
fn from(value: &'a str) -> Self {
|
||||
Self::String(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<i32> for Data<'_> {
|
||||
impl From<i32> for DataRef<'_> {
|
||||
fn from(value: i32) -> Self {
|
||||
Self::Int(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a OwnedData> for Data<'a> {
|
||||
fn from(value: &'a OwnedData) -> Self {
|
||||
impl<'a> From<&'a Data> for DataRef<'a> {
|
||||
fn from(value: &'a Data) -> Self {
|
||||
match value {
|
||||
OwnedData::String(s) => Data::String(s),
|
||||
OwnedData::Int(i) => Data::Int(*i),
|
||||
Data::String(s) => DataRef::String(s),
|
||||
Data::Int(i) => DataRef::Int(*i),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use core::panic;
|
|||
use crate::experimental::trait_based::{
|
||||
data::{
|
||||
io::{Inputs, Outputs},
|
||||
raw::Data,
|
||||
raw::DataRef,
|
||||
},
|
||||
element::{DataType, ElementSignature, PipelineElement},
|
||||
};
|
||||
|
@ -14,7 +14,7 @@ pub struct Add(pub i32);
|
|||
impl PipelineElement for Add {
|
||||
fn runner(&self) -> fn(&Inputs) -> Outputs {
|
||||
|input| {
|
||||
if let [Data::Int(i0), Data::Int(i1), ..] = input.inner()[..] {
|
||||
if let [DataRef::Int(i0), DataRef::Int(i1), ..] = input.inner()[..] {
|
||||
(i0 + i1).into()
|
||||
} else {
|
||||
panic!("Invalid data passed")
|
||||
|
@ -35,7 +35,7 @@ pub struct Subtract(pub i32);
|
|||
impl PipelineElement for Subtract {
|
||||
fn runner(&self) -> fn(&Inputs) -> Outputs {
|
||||
|input| {
|
||||
if let [Data::Int(i0), Data::Int(i1), ..] = input.inner()[..] {
|
||||
if let [DataRef::Int(i0), DataRef::Int(i1), ..] = input.inner()[..] {
|
||||
(i0 + i1).into()
|
||||
} else {
|
||||
panic!("Invalid data passed")
|
||||
|
@ -56,7 +56,7 @@ pub struct Stringify;
|
|||
impl PipelineElement for Stringify {
|
||||
fn runner(&self) -> fn(&Inputs) -> Outputs {
|
||||
|input| {
|
||||
if let [Data::Int(int), ..] = input.inner()[..] {
|
||||
if let [DataRef::Int(int), ..] = input.inner()[..] {
|
||||
int.to_string().into()
|
||||
} else {
|
||||
panic!("Invalid data passed")
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
use crate::experimental::trait_based::{
|
||||
data::{
|
||||
io::{Inputs, Outputs},
|
||||
raw::Data,
|
||||
raw::DataRef,
|
||||
},
|
||||
element::{DataType, ElementSignature, PipelineElement},
|
||||
};
|
||||
|
@ -12,7 +12,7 @@ pub struct Concatenate(pub String);
|
|||
impl PipelineElement for Concatenate {
|
||||
fn runner(&self) -> fn(&Inputs) -> Outputs {
|
||||
|input| {
|
||||
if let [Data::String(s0), Data::String(s1), ..] = input.inner()[..] {
|
||||
if let [DataRef::String(s0), DataRef::String(s1), ..] = input.inner()[..] {
|
||||
format!("{s0}{s1}").into()
|
||||
} else {
|
||||
panic!("Invalid data passed")
|
||||
|
@ -33,7 +33,7 @@ pub struct Upper;
|
|||
impl PipelineElement for Upper {
|
||||
fn runner(&self) -> fn(&Inputs) -> Outputs {
|
||||
|input| {
|
||||
if let [Data::String(s), ..] = input.inner()[..] {
|
||||
if let [DataRef::String(s), ..] = input.inner()[..] {
|
||||
s.to_uppercase().into()
|
||||
} else {
|
||||
panic!("Invalid data passed")
|
||||
|
@ -54,7 +54,7 @@ pub struct Lower;
|
|||
impl PipelineElement for Lower {
|
||||
fn runner(&self) -> fn(&Inputs) -> Outputs {
|
||||
|input| {
|
||||
if let [Data::String(s), ..] = input.inner()[..] {
|
||||
if let [DataRef::String(s), ..] = input.inner()[..] {
|
||||
s.to_lowercase().into()
|
||||
} else {
|
||||
panic!("Invalid data passed")
|
||||
|
|
Loading…
Reference in a new issue
Quite ambiguous doc-comment also regarding the rather lengthy doc-comment on the type itself.
How about removing this method altogether and making the content of
Inputs
directly public,given that one's free to convert from/to it already?