Browse Source

Implement `template` command to create new operators and custom nodes

tags/v0.0.0-test.4
Philipp Oppermann 3 years ago
parent
commit
22a39da66a
Failed to extract signature
10 changed files with 216 additions and 2 deletions
  1. +30
    -2
      binaries/cli/src/main.rs
  2. +0
    -0
      binaries/cli/src/template/c.rs
  3. +0
    -0
      binaries/cli/src/template/cxx.rs
  4. +13
    -0
      binaries/cli/src/template/mod.rs
  5. +23
    -0
      binaries/cli/src/template/python/mod.rs
  6. +91
    -0
      binaries/cli/src/template/rust/mod.rs
  7. +9
    -0
      binaries/cli/src/template/rust/node/Cargo-template.toml
  8. +15
    -0
      binaries/cli/src/template/rust/node/main-template.rs
  9. +12
    -0
      binaries/cli/src/template/rust/operator/Cargo-template.toml
  10. +23
    -0
      binaries/cli/src/template/rust/operator/lib-template.rs

+ 30
- 2
binaries/cli/src/main.rs View File

@@ -6,6 +6,7 @@ use tempfile::NamedTempFile;
mod build;
mod check;
mod graph;
mod template;

#[derive(Debug, clap::Parser)]
#[clap(version)]
@@ -30,7 +31,10 @@ enum Command {
Build {
dataflow: PathBuf,
},
Templates,
New {
#[clap(flatten)]
args: CommandNew,
},
Dashboard,
Start,
Stop,
@@ -42,6 +46,30 @@ enum Command {
Upgrade,
}

#[derive(Debug, clap::Args)]
pub struct CommandNew {
#[clap(long, value_enum, default_value_t = Kind::Operator)]
kind: Kind,
#[clap(long, value_enum, default_value_t = Lang::Rust)]
lang: Lang,
name: String,
path: Option<PathBuf>,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
enum Kind {
Operator,
CustomNode,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)]
enum Lang {
Rust,
Python,
C,
Cxx,
}

fn main() -> eyre::Result<()> {
let args = Args::parse();

@@ -83,7 +111,7 @@ fn main() -> eyre::Result<()> {
Command::Build { dataflow } => {
build::build(&dataflow)?;
}
Command::Templates => todo!(),
Command::New { args } => template::create(args)?,
Command::Dashboard => todo!(),
Command::Start => todo!(),
Command::Stop => todo!(),


+ 0
- 0
binaries/cli/src/template/c.rs View File


+ 0
- 0
binaries/cli/src/template/cxx.rs View File


+ 13
- 0
binaries/cli/src/template/mod.rs View File

@@ -0,0 +1,13 @@
mod c;
mod cxx;
mod python;
mod rust;

pub fn create(args: crate::CommandNew) -> eyre::Result<()> {
match args.lang {
crate::Lang::Rust => rust::create(args),
crate::Lang::Python => python::create(args),
crate::Lang::C => todo!(),
crate::Lang::Cxx => todo!(),
}
}

+ 23
- 0
binaries/cli/src/template/python/mod.rs View File

@@ -0,0 +1,23 @@
use std::path::PathBuf;

pub fn create(args: crate::CommandNew) -> eyre::Result<()> {
let crate::CommandNew {
kind,
lang: _,
name,
path,
} = args;

match kind {
crate::Kind::Operator => create_operator(name, path),
crate::Kind::CustomNode => create_custom_node(name, path),
}
}

fn create_operator(name: String, path: Option<PathBuf>) -> Result<(), eyre::ErrReport> {
todo!()
}

fn create_custom_node(name: String, path: Option<PathBuf>) -> Result<(), eyre::ErrReport> {
todo!()
}

+ 91
- 0
binaries/cli/src/template/rust/mod.rs View File

@@ -0,0 +1,91 @@
use eyre::{bail, Context};
use std::{
fs,
path::{Path, PathBuf},
};

pub fn create(args: crate::CommandNew) -> eyre::Result<()> {
let crate::CommandNew {
kind,
lang: _,
name,
path,
} = args;

match kind {
crate::Kind::Operator => create_operator(name, path),
crate::Kind::CustomNode => create_custom_node(name, path),
}
}

fn create_operator(name: String, path: Option<PathBuf>) -> Result<(), eyre::ErrReport> {
const CARGO_TOML: &str = include_str!("operator/Cargo-template.toml");
const LIB_RS: &str = include_str!("operator/lib-template.rs");

if name.contains('/') {
bail!("operator name must not contain `/` separators");
}
if !name.is_ascii() {
bail!("operator name must be ASCII");
}

// create directories
let root = path.as_deref().unwrap_or(Path::new(&name));
fs::create_dir(&root)
.with_context(|| format!("failed to create directory `{}`", root.display()))?;
let src = root.join("src");
fs::create_dir(&src)
.with_context(|| format!("failed to create directory `{}`", src.display()))?;

let cargo_toml = CARGO_TOML.replace("___name___", &name);
let cargo_toml_path = root.join("Cargo.toml");
fs::write(&cargo_toml_path, &cargo_toml)
.with_context(|| format!("failed to write `{}`", cargo_toml_path.display()))?;

let lib_rs_path = src.join("lib.rs");
fs::write(&lib_rs_path, LIB_RS)
.with_context(|| format!("failed to write `{}`", lib_rs_path.display()))?;

println!(
"Created new Rust operator `{name}` at {}",
Path::new(".").join(root).display()
);

Ok(())
}

fn create_custom_node(name: String, path: Option<PathBuf>) -> Result<(), eyre::ErrReport> {
const CARGO_TOML: &str = include_str!("node/Cargo-template.toml");
const MAIN_RS: &str = include_str!("node/main-template.rs");

if name.contains('/') {
bail!("node name must not contain `/` separators");
}
if !name.is_ascii() {
bail!("node name must be ASCII");
}

// create directories
let root = path.as_deref().unwrap_or(Path::new(&name));
fs::create_dir(&root)
.with_context(|| format!("failed to create directory `{}`", root.display()))?;
let src = root.join("src");
fs::create_dir(&src)
.with_context(|| format!("failed to create directory `{}`", src.display()))?;

let cargo_toml = CARGO_TOML.replace("___name___", &name);
let cargo_toml_path = root.join("Cargo.toml");
fs::write(&cargo_toml_path, &cargo_toml)
.with_context(|| format!("failed to write `{}`", cargo_toml_path.display()))?;

let main_rs_path = src.join("main.rs");
fs::write(&main_rs_path, MAIN_RS)
.with_context(|| format!("failed to write `{}`", main_rs_path.display()))?;

println!(
"Created new Rust custom node `{name}` at {}",
Path::new(".").join(root).display()
);

Ok(())
}

+ 9
- 0
binaries/cli/src/template/rust/node/Cargo-template.toml View File

@@ -0,0 +1,9 @@
[package]
name = "___name___"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
dora-node-api = "0.1.0"

+ 15
- 0
binaries/cli/src/template/rust/node/main-template.rs View File

@@ -0,0 +1,15 @@
use dora_node_api::{self, config::DataId, DoraNode};
use std::error::Error;

fn main() -> Result<(), Box<dyn Error>> {
let mut node = DoraNode::init_from_env()?;
let inputs = node.inputs()?;

while let Ok(input) = inputs.recv() {
match input.id.as_str() {
other => eprintln!("Ignoring unexpected input `{other}`"),
}
}

Ok(())
}

+ 12
- 0
binaries/cli/src/template/rust/operator/Cargo-template.toml View File

@@ -0,0 +1,12 @@
[package]
name = "___name___"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[lib]
crate-type = ["cdylib"]

[dependencies]
dora-operator-api = "0.1.0"

+ 23
- 0
binaries/cli/src/template/rust/operator/lib-template.rs View File

@@ -0,0 +1,23 @@
use dora_operator_api::{register_operator, DoraOperator, DoraOutputSender, DoraStatus};
use std::time::{Duration, Instant};

register_operator!(ExampleOperator);

#[derive(Debug, Default)]
struct ExampleOperator {
example_field: u32,
}

impl DoraOperator for ExampleOperator {
fn on_input(
&mut self,
id: &str,
data: &[u8],
output_sender: &mut DoraOutputSender,
) -> Result<DoraStatus, String> {
match id {
other => eprintln!("ignoring unexpected input {other}"),
}
Ok(DoraStatus::Continue)
}
}

Loading…
Cancel
Save