diff --git a/crates/dagger-codegen/src/functions.rs b/crates/dagger-codegen/src/functions.rs index a55b50d..f395706 100644 --- a/crates/dagger-codegen/src/functions.rs +++ b/crates/dagger-codegen/src/functions.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use dagger_core::introspection::{FullType, InputValue, TypeRef, __TypeKind}; +use dagger_core::introspection::{FullType, FullTypeFields, InputValue, TypeRef, __TypeKind}; use eyre::ContextCompat; use crate::utility::OptionExt; @@ -154,6 +154,19 @@ pub fn type_ref_is_optional(type_ref: &TypeRef) -> bool { .unwrap_or(false) } +pub fn type_field_has_optional(field: &FullTypeFields) -> bool { + field + .args + .pipe(|a| { + a.iter() + .map(|a| a.pipe(|a| &a.input_value)) + .flatten() + .collect::>() + }) + .pipe(|s| input_values_has_optionals(s.as_slice())) + .unwrap_or(false) +} + pub fn type_ref_is_scalar(type_ref: &TypeRef) -> bool { type_ref .kind @@ -175,7 +188,7 @@ pub fn type_ref_is_list(type_ref: &TypeRef) -> bool { .unwrap_or(false) } -pub fn input_values_has_optionals(input_values: &[InputValue]) -> bool { +pub fn input_values_has_optionals(input_values: &[&InputValue]) -> bool { input_values .into_iter() .map(|k| type_ref_is_optional(&k.type_)) @@ -324,7 +337,7 @@ mod test { }, ]; - let output = input_values_has_optionals(&input); + let output = input_values_has_optionals(input.iter().collect::>().as_slice()); assert_eq!(output, true); } @@ -354,7 +367,7 @@ mod test { }, ]; - let output = input_values_has_optionals(&input); + let output = input_values_has_optionals(input.iter().collect::>().as_slice()); assert_eq!(output, false); } diff --git a/crates/dagger-codegen/src/rust/format.rs b/crates/dagger-codegen/src/rust/format.rs index ad7af38..1f32f30 100644 --- a/crates/dagger-codegen/src/rust/format.rs +++ b/crates/dagger-codegen/src/rust/format.rs @@ -40,7 +40,7 @@ impl FormatTypeFuncs for FormatTypeFunc { input: bool, ) -> String { let mut rep = representation.to_string(); - rep.push_str(ref_name); + rep.push_str(&format_name(ref_name)); rep } @@ -58,7 +58,7 @@ impl FormatTypeFuncs for FormatTypeFunc { fn format_kind_enum(&self, representation: &str, ref_name: &str) -> String { let mut rep = representation.to_string(); - rep.push_str(ref_name); + rep.push_str(&format_name(ref_name)); rep } } diff --git a/crates/dagger-codegen/src/rust/functions.rs b/crates/dagger-codegen/src/rust/functions.rs index 5b97792..1069bc8 100644 --- a/crates/dagger-codegen/src/rust/functions.rs +++ b/crates/dagger-codegen/src/rust/functions.rs @@ -1,5 +1,12 @@ use convert_case::{Case, Casing}; use dagger_core::introspection::FullTypeFields; +use genco::prelude::rust; +use genco::quote; + +use crate::functions::{ + input_values_has_optionals, type_field_has_optional, type_ref_is_optional, CommonFunctions, +}; +use crate::utility::OptionExt; pub fn format_name(s: &str) -> String { s.to_case(Case::Pascal) @@ -18,3 +25,61 @@ pub fn field_options_struct_name(field: &FullTypeFields) -> Option { .zip(field.name.as_ref().map(|n| format_name(n))) .map(|(parent_name, field_name)| format!("{parent_name}{field_name}Opts")) } + +pub fn format_function(funcs: &CommonFunctions, field: &FullTypeFields) -> Option { + let signature = quote! { + pub fn $(field.name.pipe(|n | format_struct_name(n))) + }; + let args = format_function_args(funcs, field); + + let output_type = field + .type_ + .pipe(|t| &t.type_ref) + .pipe(|t| funcs.format_output_type(t)); + + Some(quote! { + $(signature)( + $(args) + ) -> $(output_type) { + todo!() + } + }) +} + +fn format_function_args(funcs: &CommonFunctions, field: &FullTypeFields) -> Option { + if let Some(args) = field.args.as_ref() { + let args = args + .into_iter() + .map(|a| { + a.as_ref().and_then(|s| { + if type_ref_is_optional(&s.input_value.type_) { + return None; + } + + let t = funcs.format_input_type(&s.input_value.type_); + let n = format_struct_name(&s.input_value.name); + + Some(quote! { + $(n): $(t), + }) + }) + }) + .flatten() + .collect::>(); + let required_args = quote! { + &self, + $(for arg in args join ($['\r']) => $arg) + }; + + if type_field_has_optional(field) { + Some(quote! { + $(required_args) + opts: Option<$(field_options_struct_name(field))> + }) + } else { + Some(required_args) + } + } else { + None + } +} diff --git a/crates/dagger-codegen/src/rust/templates/object_tmpl.rs b/crates/dagger-codegen/src/rust/templates/object_tmpl.rs index 4cbaeb4..9b09f80 100644 --- a/crates/dagger-codegen/src/rust/templates/object_tmpl.rs +++ b/crates/dagger-codegen/src/rust/templates/object_tmpl.rs @@ -2,8 +2,12 @@ use dagger_core::introspection::{FullType, FullTypeFields, FullTypeFieldsArgs}; use genco::prelude::rust; use genco::quote; -use crate::functions::CommonFunctions; -use crate::rust::functions::{field_options_struct_name, format_name, format_struct_name}; +use crate::functions::{ + input_values_has_optionals, type_field_has_optional, type_ref_is_optional, CommonFunctions, +}; +use crate::rust::functions::{ + field_options_struct_name, format_function, format_name, format_struct_name, +}; use crate::utility::OptionExt; pub fn render_object(funcs: &CommonFunctions, t: &FullType) -> eyre::Result { @@ -15,7 +19,7 @@ pub fn render_object(funcs: &CommonFunctions, t: &FullType) -> eyre::Result Optio let fields = field .args .pipe(|t| t.into_iter().flatten().collect::>()) + .map(|t| { + t.into_iter() + .filter(|t| type_ref_is_optional(&t.input_value.type_)) + .collect::>() + }) .pipe(|t| render_optional_field_args(funcs, t)) .flatten(); @@ -67,7 +76,7 @@ fn render_optional_field_args( } let rendered_args = args.into_iter().map(|a| &a.input_value).map(|a| { quote! { - pub $(format_struct_name(&a.name)): $(funcs.format_output_type(&a.type_)), + pub $(format_struct_name(&a.name)): Option<$(funcs.format_output_type(&a.type_))>, } }); @@ -75,3 +84,24 @@ fn render_optional_field_args( $(for arg in rendered_args join ($['\r']) => $arg) }) } + +fn render_functions(funcs: &CommonFunctions, fields: &Vec) -> Option { + let rendered_functions = fields + .iter() + .map(|f| render_function(funcs, f)) + .collect::>(); + + if rendered_functions.len() > 0 { + Some(quote! { + $(for func in rendered_functions join ($['\r']) => $func) + }) + } else { + None + } +} + +fn render_function(funcs: &CommonFunctions, field: &FullTypeFields) -> Option { + Some(quote! { + $(format_function(funcs, field)) + }) +} diff --git a/crates/dagger-codegen/src/rust/templates/scalar_tmpl.rs b/crates/dagger-codegen/src/rust/templates/scalar_tmpl.rs index 0b0cdcc..7e2f84b 100644 --- a/crates/dagger-codegen/src/rust/templates/scalar_tmpl.rs +++ b/crates/dagger-codegen/src/rust/templates/scalar_tmpl.rs @@ -3,9 +3,10 @@ use genco::prelude::rust; use genco::quote; use crate::rust::functions::format_name; +use crate::utility::OptionExt; pub fn render_scalar(t: &FullType) -> eyre::Result { Ok(quote! { - pub struct $(format_name(&t.name.as_ref().unwrap()))(String); + pub struct $(t.name.pipe(|n|format_name(n)))(String); }) } diff --git a/crates/dagger-sdk/src/gen.rs b/crates/dagger-sdk/src/gen.rs index 2bea18e..fe0f8b7 100644 --- a/crates/dagger-sdk/src/gen.rs +++ b/crates/dagger-sdk/src/gen.rs @@ -9,361 +9,519 @@ pub struct BuildArg { pub name: String, pub value: String, } -pub struct CacheVolume { - -} +pub struct CacheVolume {} impl CacheVolume { - -} -pub struct Container { - + pub fn id(&self) -> CacheId { + todo!() + } } +pub struct Container {} pub struct ContainerBuildOpts { - pub context: DirectoryID, - pub dockerfile: String, - pub build_args: Vec, - pub target: String, -} -pub struct ContainerDirectoryOpts { - pub path: String, -} -pub struct ContainerEnvVariableOpts { - pub name: String, + pub dockerfile: Option, + pub build_args: Option>, + pub target: Option, } pub struct ContainerExecOpts { - pub args: Vec, - pub stdin: String, - pub redirect_stdout: String, - pub redirect_stderr: String, - pub experimental_privileged_nesting: bool, + pub args: Option>, + pub stdin: Option, + pub redirect_stdout: Option, + pub redirect_stderr: Option, + pub experimental_privileged_nesting: Option, } pub struct ContainerExportOpts { - pub path: String, - pub platform_variants: Vec, -} -pub struct ContainerFileOpts { - pub path: String, -} -pub struct ContainerFromOpts { - pub address: String, -} -pub struct ContainerLabelOpts { - pub name: String, + pub platform_variants: Option>, } pub struct ContainerPipelineOpts { - pub name: String, - pub description: String, + pub description: Option, } pub struct ContainerPublishOpts { - pub address: String, - pub platform_variants: Vec, + pub platform_variants: Option>, } pub struct ContainerWithDefaultArgsOpts { - pub args: Vec, + pub args: Option>, } pub struct ContainerWithDirectoryOpts { - pub path: String, - pub directory: DirectoryID, - pub exclude: Vec, - pub include: Vec, -} -pub struct ContainerWithEntrypointOpts { - pub args: Vec, -} -pub struct ContainerWithEnvVariableOpts { - pub name: String, - pub value: String, + pub exclude: Option>, + pub include: Option>, } pub struct ContainerWithExecOpts { - pub args: Vec, - pub stdin: String, - pub redirect_stdout: String, - pub redirect_stderr: String, - pub experimental_privileged_nesting: bool, -} -pub struct ContainerWithFsOpts { - pub id: DirectoryID, + pub stdin: Option, + pub redirect_stdout: Option, + pub redirect_stderr: Option, + pub experimental_privileged_nesting: Option, } pub struct ContainerWithFileOpts { - pub path: String, - pub source: FileID, - pub permissions: isize, -} -pub struct ContainerWithLabelOpts { - pub name: String, - pub value: String, + pub permissions: Option, } pub struct ContainerWithMountedCacheOpts { - pub path: String, - pub cache: CacheID, - pub source: DirectoryID, -} -pub struct ContainerWithMountedDirectoryOpts { - pub path: String, - pub source: DirectoryID, -} -pub struct ContainerWithMountedFileOpts { - pub path: String, - pub source: FileID, -} -pub struct ContainerWithMountedSecretOpts { - pub path: String, - pub source: SecretID, -} -pub struct ContainerWithMountedTempOpts { - pub path: String, + pub source: Option, } pub struct ContainerWithNewFileOpts { - pub path: String, - pub contents: String, - pub permissions: isize, -} -pub struct ContainerWithRootfsOpts { - pub id: DirectoryID, -} -pub struct ContainerWithSecretVariableOpts { - pub name: String, - pub secret: SecretID, -} -pub struct ContainerWithUnixSocketOpts { - pub path: String, - pub source: SocketID, -} -pub struct ContainerWithUserOpts { - pub name: String, -} -pub struct ContainerWithWorkdirOpts { - pub path: String, -} -pub struct ContainerWithoutEnvVariableOpts { - pub name: String, -} -pub struct ContainerWithoutLabelOpts { - pub name: String, -} -pub struct ContainerWithoutMountOpts { - pub path: String, -} -pub struct ContainerWithoutUnixSocketOpts { - pub path: String, + pub contents: Option, + pub permissions: Option, } impl Container { + pub fn build(&self, context: DirectoryId, opts: Option) -> Container { + todo!() + } + pub fn default_args(&self) -> Vec { + todo!() + } + pub fn directory(&self, path: String) -> Directory { + todo!() + } + pub fn entrypoint(&self) -> Vec { + todo!() + } + pub fn env_variable(&self, name: String) -> String { + todo!() + } + pub fn env_variables(&self) -> Vec { + todo!() + } + pub fn exec(&self, opts: Option) -> Container { + todo!() + } + pub fn exit_code(&self) -> isize { + todo!() + } + pub fn export(&self, path: String, opts: Option) -> bool { + todo!() + } + pub fn file(&self, path: String) -> File { + todo!() + } + pub fn from(&self, address: String) -> Container { + todo!() + } + pub fn fs(&self) -> Directory { + todo!() + } + pub fn id(&self) -> ContainerId { + todo!() + } + pub fn label(&self, name: String) -> String { + todo!() + } + pub fn labels(&self) -> Vec