Skip to content

Commit

Permalink
parse params based on doc
Browse files Browse the repository at this point in the history
  • Loading branch information
dzhou121 committed Apr 11, 2024
1 parent 3aeb100 commit 714ff1d
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 30 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tiron-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ version.workspace = true
edition.workspace = true

[dependencies]
itertools = { workspace = true }
tempfile = { workspace = true }
serde_json = { workspace = true }
os_info = { workspace = true }
Expand Down
48 changes: 24 additions & 24 deletions tiron-node/src/action/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,30 @@ impl Action for CopyAction {
"copy".to_string()
}

fn doc(&self) -> ActionDoc {
ActionDoc {
description: CopyAction::DOCS.to_string(),
params: vec![
ActionParamDoc {
name: "src".to_string(),
required: true,
description: CopyAction::get_field_docs("src")
.unwrap_or_default()
.to_string(),
type_: vec![ActionParamType::String],
},
ActionParamDoc {
name: "dest".to_string(),
required: true,
description: CopyAction::get_field_docs("dest")
.unwrap_or_default()
.to_string(),
type_: vec![ActionParamType::String],
},
],
}
}

fn input(&self, cwd: &Path, params: Option<&Value>) -> Result<Vec<u8>, Error> {
let Some(value) = params else {
return Error::new("can't find params").err();
Expand Down Expand Up @@ -92,28 +116,4 @@ impl Action for CopyAction {
Err(anyhow!("can't copy to {}", input.dest))
}
}

fn doc(&self) -> ActionDoc {
ActionDoc {
description: CopyAction::DOCS.to_string(),
params: vec![
ActionParamDoc {
name: "src".to_string(),
required: true,
description: CopyAction::get_field_docs("src")
.unwrap_or_default()
.to_string(),
type_: vec![ActionParamType::String],
},
ActionParamDoc {
name: "dest".to_string(),
required: true,
description: CopyAction::get_field_docs("dest")
.unwrap_or_default()
.to_string(),
type_: vec![ActionParamType::String],
},
],
}
}
}
8 changes: 6 additions & 2 deletions tiron-node/src/action/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use documented::{Documented, DocumentedFields};
use rcl::{error::Error, runtime::Value};
use serde::{Deserialize, Serialize};

use super::{Action, ActionDoc, ActionParamDoc, ActionParamType};
use super::{Action, ActionDoc, ActionParamBaseValue, ActionParamDoc, ActionParamType};

#[derive(Default, Clone, Serialize, Deserialize)]
pub enum FileState {
Expand Down Expand Up @@ -125,7 +125,11 @@ impl Action for FileAction {
description: Self::get_field_docs("state")
.unwrap_or_default()
.to_string(),
type_: vec![ActionParamType::String],
type_: vec![ActionParamType::Enum(vec![
ActionParamBaseValue::String("file".to_string()),
ActionParamBaseValue::String("absent".to_string()),
ActionParamBaseValue::String("directory".to_string()),
])],
},
],
}
Expand Down
151 changes: 149 additions & 2 deletions tiron-node/src/action/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ mod file;
mod git;
mod package;

use std::fmt::Display;
use std::{collections::BTreeMap, fmt::Display};

use crossbeam_channel::Sender;
use rcl::error::Error;
use itertools::Itertools;
use rcl::{error::Error, runtime::Value, source::Span};
use tiron_common::action::{ActionId, ActionMessage};

pub trait Action {
Expand All @@ -35,6 +36,19 @@ pub enum ActionParamBaseType {
String,
}

impl ActionParamBaseType {
fn parse(&self, value: &Value) -> Option<ActionParamBaseValue> {
match self {
ActionParamBaseType::String => {
if let Value::String(s, _) = value {
return Some(ActionParamBaseValue::String(s.to_string()));
}
}
}
None
}
}

impl Display for ActionParamBaseType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Expand All @@ -47,6 +61,42 @@ pub enum ActionParamType {
String,
Boolean,
List(ActionParamBaseType),
Enum(Vec<ActionParamBaseValue>),
}

impl ActionParamType {
fn parse(&self, value: &Value) -> Option<ActionParamValue> {
match self {
ActionParamType::String => {
if let Value::String(s, _) = value {
return Some(ActionParamValue::String(s.to_string()));
}
}
ActionParamType::Boolean => {
if let Value::Bool(v) = value {
return Some(ActionParamValue::Boolean(*v));
}
}
ActionParamType::List(base) => {
if let Value::List(v) = value {
let mut items = Vec::new();
for v in v.iter() {
let base = base.parse(v)?;
items.push(base);
}
return Some(ActionParamValue::List(items));
}
}
ActionParamType::Enum(options) => {
for option in options {
if option.match_value(value) {
return Some(ActionParamValue::Base(option.clone()));
}
}
}
}
None
}
}

impl Display for ActionParamType {
Expand All @@ -55,6 +105,13 @@ impl Display for ActionParamType {
ActionParamType::String => f.write_str("String"),
ActionParamType::Boolean => f.write_str("Boolean"),
ActionParamType::List(t) => f.write_str(&format!("List of {t}")),
ActionParamType::Enum(t) => f.write_str(&format!(
"Enum of {}",
t.iter()
.map(|v| v.to_string())
.collect::<Vec<_>>()
.join(", ")
)),
}
}
}
Expand All @@ -66,7 +123,97 @@ pub struct ActionParamDoc {
pub description: String,
}

impl ActionParamDoc {
pub fn parse_param(
&self,
dict: &BTreeMap<Value, Value>,
dict_span: Option<Span>,
) -> Result<Option<ActionParamValue>, Error> {
let param = dict.get(&Value::String(self.name.clone().into(), None));
if let Some(param) = param {
for type_ in &self.type_ {
if let Some(value) = type_.parse(param) {
return Ok(Some(value));
}
}
return Error::new(format!(
"{} type should be {}",
self.name,
self.type_.iter().map(|t| t.to_string()).join(" or ")
))
.with_origin(*param.span())
.err();
}

if self.required {
return Error::new(format!("can't find {}", self.name,))
.with_origin(dict_span)
.err();
}

Ok(None)
}
}

pub struct ActionDoc {
pub description: String,
pub params: Vec<ActionParamDoc>,
}

impl ActionDoc {
pub fn parse_params(
&self,
params: Option<&Value>,
) -> Result<Vec<Option<ActionParamValue>>, Error> {
let Some(value) = params else {
return Error::new("can't find params").err();
};
let Value::Dict(dict, dict_span) = value else {
return Error::new("params should be a Dict")
.with_origin(*value.span())
.err();
};

let mut values = Vec::new();
for param in &self.params {
let value = param.parse_param(dict, *dict_span)?;
values.push(value);
}

Ok(values)
}
}

pub enum ActionParamValue {
String(String),
Boolean(bool),
List(Vec<ActionParamBaseValue>),
Base(ActionParamBaseValue),
}

#[derive(Clone)]
pub enum ActionParamBaseValue {
String(String),
}

impl ActionParamBaseValue {
fn match_value(&self, value: &Value) -> bool {
match self {
ActionParamBaseValue::String(base) => {
if let Value::String(s, _) = value {
return base == &s.to_string();
}
}
}

false
}
}

impl Display for ActionParamBaseValue {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ActionParamBaseValue::String(s) => f.write_str(&format!("\"{s}\"")),
}
}
}
10 changes: 8 additions & 2 deletions tiron-node/src/action/package/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use tiron_common::action::{ActionId, ActionMessage};

use self::provider::PackageProvider;

use super::{Action, ActionDoc, ActionParamBaseType, ActionParamDoc, ActionParamType};
use super::{
Action, ActionDoc, ActionParamBaseType, ActionParamBaseValue, ActionParamDoc, ActionParamType,
};

#[derive(Default, Clone, Serialize, Deserialize)]
pub enum PackageState {
Expand Down Expand Up @@ -137,7 +139,11 @@ impl Action for PackageAction {
description: PackageAction::get_field_docs("state")
.unwrap_or_default()
.to_string(),
type_: vec![ActionParamType::String],
type_: vec![ActionParamType::Enum(vec![
ActionParamBaseValue::String("present".to_string()),
ActionParamBaseValue::String("absent".to_string()),
ActionParamBaseValue::String("latest".to_string()),
])],
},
],
}
Expand Down
1 change: 1 addition & 0 deletions tiron/src/action.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ pub fn parse_actions(
.err();
};
let params = dict.get(&Value::String("params".into(), None));
let _ = action.doc().parse_params(params)?;
let input = action.input(cwd, params).map_err(|e| {
let mut e = e;
if e.origin.is_none() {
Expand Down

0 comments on commit 714ff1d

Please sign in to comment.