mirror of
https://github.com/kjuulh/dagger-rs.git
synced 2025-02-23 08:11:12 +01:00
add object
This commit is contained in:
parent
46f0b4d841
commit
4ebd1b4b17
@ -1,6 +1,8 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use dagger_core::introspection::{TypeRef, __TypeKind};
|
use dagger_core::introspection::{FullType, InputValue, TypeRef, __TypeKind};
|
||||||
|
|
||||||
|
use crate::utility::OptionExt;
|
||||||
|
|
||||||
pub trait FormatTypeFuncs {
|
pub trait FormatTypeFuncs {
|
||||||
fn format_kind_list(&self, representation: &str) -> String;
|
fn format_kind_list(&self, representation: &str) -> String;
|
||||||
@ -44,62 +46,66 @@ impl CommonFunctions {
|
|||||||
let mut representation = String::new();
|
let mut representation = String::new();
|
||||||
let mut r = Some(t.clone());
|
let mut r = Some(t.clone());
|
||||||
while r.is_some() {
|
while r.is_some() {
|
||||||
match r.as_ref() {
|
return match r.as_ref() {
|
||||||
Some(rf) => match rf.kind.as_ref() {
|
Some(rf) => match rf.kind.as_ref() {
|
||||||
Some(k) => match k {
|
Some(k) => match k {
|
||||||
__TypeKind::SCALAR => match Scalar::from(rf) {
|
__TypeKind::SCALAR => match Scalar::from(rf) {
|
||||||
Scalar::Int => {
|
Scalar::Int => self
|
||||||
self.format_type_funcs
|
.format_type_funcs
|
||||||
.format_kind_scalar_int(&mut representation);
|
.format_kind_scalar_int(&mut representation),
|
||||||
}
|
Scalar::Float => self
|
||||||
Scalar::Float => {
|
.format_type_funcs
|
||||||
self.format_type_funcs
|
.format_kind_scalar_float(&mut representation),
|
||||||
.format_kind_scalar_float(&mut representation);
|
Scalar::String => self
|
||||||
}
|
.format_type_funcs
|
||||||
Scalar::String => {
|
.format_kind_scalar_string(&mut representation),
|
||||||
self.format_type_funcs
|
Scalar::Boolean => self
|
||||||
.format_kind_scalar_string(&mut representation);
|
.format_type_funcs
|
||||||
}
|
.format_kind_scalar_boolean(&mut representation),
|
||||||
Scalar::Boolean => {
|
Scalar::Default => self.format_type_funcs.format_kind_scalar_default(
|
||||||
self.format_type_funcs
|
&mut representation,
|
||||||
.format_kind_scalar_boolean(&mut representation);
|
rf.name.as_ref().unwrap(),
|
||||||
}
|
input,
|
||||||
Scalar::Default => {
|
),
|
||||||
self.format_type_funcs.format_kind_scalar_default(
|
|
||||||
&mut representation,
|
|
||||||
rf.name.as_ref().unwrap(),
|
|
||||||
input,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
__TypeKind::OBJECT => {
|
__TypeKind::OBJECT => self
|
||||||
self.format_type_funcs
|
.format_type_funcs
|
||||||
.format_kind_object(&mut representation, rf.name.as_ref().unwrap());
|
.format_kind_object(&mut representation, rf.name.as_ref().unwrap()),
|
||||||
}
|
__TypeKind::ENUM => self
|
||||||
__TypeKind::ENUM => {
|
.format_type_funcs
|
||||||
self.format_type_funcs
|
.format_kind_enum(&mut representation, rf.name.as_ref().unwrap()),
|
||||||
.format_kind_enum(&mut representation, rf.name.as_ref().unwrap());
|
|
||||||
}
|
|
||||||
__TypeKind::INPUT_OBJECT => {
|
__TypeKind::INPUT_OBJECT => {
|
||||||
self.format_type_funcs.format_kind_input_object(
|
self.format_type_funcs.format_kind_input_object(
|
||||||
&mut representation,
|
&mut representation,
|
||||||
&rf.name.as_ref().unwrap(),
|
&rf.name.as_ref().unwrap(),
|
||||||
);
|
)
|
||||||
}
|
}
|
||||||
__TypeKind::LIST => {
|
__TypeKind::LIST => {
|
||||||
self.format_type_funcs.format_kind_list(&mut representation);
|
representation =
|
||||||
|
self.format_type_funcs.format_kind_list(&mut representation);
|
||||||
|
r = rf.of_type.as_ref().map(|t| t.clone()).map(|t| *t);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
__TypeKind::NON_NULL => {
|
||||||
|
r = rf.of_type.as_ref().map(|t| t.clone()).map(|t| *t);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
__TypeKind::Other(_) => {
|
__TypeKind::Other(_) => {
|
||||||
r = rf.of_type.as_ref().map(|t| t.clone()).map(|t| *t)
|
r = rf.of_type.as_ref().map(|t| t.clone()).map(|t| *t);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
_ => {}
|
__TypeKind::INTERFACE => break,
|
||||||
|
__TypeKind::UNION => break,
|
||||||
},
|
},
|
||||||
None => break,
|
None => break,
|
||||||
},
|
},
|
||||||
None => break,
|
None => break,
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
println!("rep: {}", representation);
|
||||||
|
println!("{:?}", t);
|
||||||
|
|
||||||
representation
|
representation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,3 +130,222 @@ impl From<&TypeRef> for Scalar {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_type_from_name<'t>(types: &'t [FullType], name: &'t str) -> Option<&'t FullType> {
|
||||||
|
types
|
||||||
|
.into_iter()
|
||||||
|
.find(|t| t.name.as_ref().map(|s| s.as_str()) == Some(name))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_ref_is_optional(type_ref: &TypeRef) -> bool {
|
||||||
|
type_ref
|
||||||
|
.kind
|
||||||
|
.pipe(|k| *k != __TypeKind::NON_NULL)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_ref_is_scalar(type_ref: &TypeRef) -> bool {
|
||||||
|
type_ref
|
||||||
|
.kind
|
||||||
|
.pipe(|k| *k == __TypeKind::SCALAR)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_ref_is_object(type_ref: &TypeRef) -> bool {
|
||||||
|
type_ref
|
||||||
|
.kind
|
||||||
|
.pipe(|k| *k == __TypeKind::OBJECT)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn type_ref_is_list(type_ref: &TypeRef) -> bool {
|
||||||
|
type_ref
|
||||||
|
.kind
|
||||||
|
.pipe(|k| *k == __TypeKind::LIST)
|
||||||
|
.unwrap_or(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_values_has_optionals(input_values: &[InputValue]) -> bool {
|
||||||
|
input_values
|
||||||
|
.into_iter()
|
||||||
|
.map(|k| type_ref_is_optional(&k.type_))
|
||||||
|
.filter(|k| *k)
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.len()
|
||||||
|
> 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input_values_is_empty(input_values: &[InputValue]) -> bool {
|
||||||
|
input_values.len() > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use dagger_core::introspection::{FullType, InputValue, TypeRef, __TypeKind};
|
||||||
|
use pretty_assertions::assert_eq;
|
||||||
|
|
||||||
|
use crate::functions::{input_values_has_optionals, type_ref_is_optional};
|
||||||
|
|
||||||
|
use super::get_type_from_name;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_type_from_name_has_no_item() {
|
||||||
|
let input = vec![];
|
||||||
|
let output = get_type_from_name(&input, "some-name");
|
||||||
|
|
||||||
|
assert_eq!(output.is_none(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_type_from_name_has_item() {
|
||||||
|
let name = "some-name";
|
||||||
|
let input = vec![FullType {
|
||||||
|
kind: None,
|
||||||
|
name: Some(name.to_string()),
|
||||||
|
description: None,
|
||||||
|
fields: None,
|
||||||
|
input_fields: None,
|
||||||
|
interfaces: None,
|
||||||
|
enum_values: None,
|
||||||
|
possible_types: None,
|
||||||
|
}];
|
||||||
|
let output = get_type_from_name(&input, name);
|
||||||
|
|
||||||
|
assert_eq!(output.is_some(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn get_type_from_name_has_item_multiple_entries() {
|
||||||
|
let name = "some-name";
|
||||||
|
let input = vec![
|
||||||
|
FullType {
|
||||||
|
kind: None,
|
||||||
|
name: Some(name.to_string()),
|
||||||
|
description: None,
|
||||||
|
fields: None,
|
||||||
|
input_fields: None,
|
||||||
|
interfaces: None,
|
||||||
|
enum_values: None,
|
||||||
|
possible_types: None,
|
||||||
|
},
|
||||||
|
FullType {
|
||||||
|
kind: None,
|
||||||
|
name: Some(name.to_string()),
|
||||||
|
description: None,
|
||||||
|
fields: None,
|
||||||
|
input_fields: None,
|
||||||
|
interfaces: None,
|
||||||
|
enum_values: None,
|
||||||
|
possible_types: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
let output = get_type_from_name(&input, name);
|
||||||
|
|
||||||
|
assert_eq!(output.is_some(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_ref_is_optional_has_none() {
|
||||||
|
let input = TypeRef {
|
||||||
|
kind: None,
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
};
|
||||||
|
let output = type_ref_is_optional(&input);
|
||||||
|
|
||||||
|
assert_eq!(output, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_ref_is_optional_is_required() {
|
||||||
|
let input = TypeRef {
|
||||||
|
kind: Some(__TypeKind::NON_NULL),
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
};
|
||||||
|
let output = type_ref_is_optional(&input);
|
||||||
|
|
||||||
|
assert_eq!(output, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn type_ref_is_optional_is_optional() {
|
||||||
|
let input = TypeRef {
|
||||||
|
kind: Some(__TypeKind::OBJECT),
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
};
|
||||||
|
let output = type_ref_is_optional(&input);
|
||||||
|
|
||||||
|
assert_eq!(output, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn input_values_has_optionals_none() {
|
||||||
|
let input = vec![];
|
||||||
|
|
||||||
|
let output = input_values_has_optionals(&input);
|
||||||
|
|
||||||
|
assert_eq!(output, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn input_values_has_optionals_has_optional() {
|
||||||
|
let input = vec![
|
||||||
|
InputValue {
|
||||||
|
name: "some-name".to_string(),
|
||||||
|
description: None,
|
||||||
|
type_: TypeRef {
|
||||||
|
kind: Some(__TypeKind::NON_NULL),
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
},
|
||||||
|
default_value: None,
|
||||||
|
},
|
||||||
|
InputValue {
|
||||||
|
name: "some-other-name".to_string(),
|
||||||
|
description: None,
|
||||||
|
type_: TypeRef {
|
||||||
|
kind: Some(__TypeKind::OBJECT),
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
},
|
||||||
|
default_value: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let output = input_values_has_optionals(&input);
|
||||||
|
|
||||||
|
assert_eq!(output, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn input_values_has_optionals_is_required() {
|
||||||
|
let input = vec![
|
||||||
|
InputValue {
|
||||||
|
name: "some-name".to_string(),
|
||||||
|
description: None,
|
||||||
|
type_: TypeRef {
|
||||||
|
kind: Some(__TypeKind::NON_NULL),
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
},
|
||||||
|
default_value: None,
|
||||||
|
},
|
||||||
|
InputValue {
|
||||||
|
name: "some-other-name".to_string(),
|
||||||
|
description: None,
|
||||||
|
type_: TypeRef {
|
||||||
|
kind: Some(__TypeKind::NON_NULL),
|
||||||
|
name: None,
|
||||||
|
of_type: None,
|
||||||
|
},
|
||||||
|
default_value: None,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
let output = input_values_has_optionals(&input);
|
||||||
|
|
||||||
|
assert_eq!(output, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
mod functions;
|
mod functions;
|
||||||
mod generator;
|
mod generator;
|
||||||
pub mod rust;
|
pub mod rust;
|
||||||
|
pub mod utility;
|
||||||
mod visitor;
|
mod visitor;
|
||||||
|
|
||||||
use dagger_core::introspection::Schema;
|
use dagger_core::introspection::Schema;
|
||||||
|
@ -8,9 +8,11 @@ use dagger_core::introspection::Schema;
|
|||||||
use eyre::Context;
|
use eyre::Context;
|
||||||
use genco::prelude::rust;
|
use genco::prelude::rust;
|
||||||
|
|
||||||
|
use crate::functions::CommonFunctions;
|
||||||
use crate::generator::Generator;
|
use crate::generator::Generator;
|
||||||
use crate::visitor::{VisitHandlers, Visitor};
|
use crate::visitor::{VisitHandlers, Visitor};
|
||||||
|
|
||||||
|
use self::format::FormatTypeFunc;
|
||||||
use self::templates::enum_tmpl::render_enum;
|
use self::templates::enum_tmpl::render_enum;
|
||||||
use self::templates::input_tmpl::render_input;
|
use self::templates::input_tmpl::render_input;
|
||||||
use self::templates::object_tmpl::render_object;
|
use self::templates::object_tmpl::render_object;
|
||||||
@ -21,6 +23,8 @@ pub struct RustGenerator {}
|
|||||||
impl Generator for RustGenerator {
|
impl Generator for RustGenerator {
|
||||||
fn generate(&self, schema: Schema) -> eyre::Result<String> {
|
fn generate(&self, schema: Schema) -> eyre::Result<String> {
|
||||||
let render = Arc::new(Mutex::new(rust::Tokens::new()));
|
let render = Arc::new(Mutex::new(rust::Tokens::new()));
|
||||||
|
let common_funcs = CommonFunctions::new(Arc::new(FormatTypeFunc {}));
|
||||||
|
println!("generating dagger for rust");
|
||||||
|
|
||||||
let visitor = Visitor {
|
let visitor = Visitor {
|
||||||
schema,
|
schema,
|
||||||
@ -28,6 +32,7 @@ impl Generator for RustGenerator {
|
|||||||
visit_scalar: Arc::new({
|
visit_scalar: Arc::new({
|
||||||
let render = render.clone();
|
let render = render.clone();
|
||||||
move |t| {
|
move |t| {
|
||||||
|
println!("generating scalar");
|
||||||
let rendered_scalar = render_scalar(t)?;
|
let rendered_scalar = render_scalar(t)?;
|
||||||
|
|
||||||
let mut render = render.lock().unwrap();
|
let mut render = render.lock().unwrap();
|
||||||
@ -35,6 +40,8 @@ impl Generator for RustGenerator {
|
|||||||
render.append(rendered_scalar);
|
render.append(rendered_scalar);
|
||||||
render.push();
|
render.push();
|
||||||
|
|
||||||
|
println!("generated scalar");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
@ -42,12 +49,14 @@ impl Generator for RustGenerator {
|
|||||||
let render = render.clone();
|
let render = render.clone();
|
||||||
|
|
||||||
move |t| {
|
move |t| {
|
||||||
|
println!("generating object");
|
||||||
let rendered_scalar = render_object(t)?;
|
let rendered_scalar = render_object(t)?;
|
||||||
|
|
||||||
let mut render = render.lock().unwrap();
|
let mut render = render.lock().unwrap();
|
||||||
|
|
||||||
render.append(rendered_scalar);
|
render.append(rendered_scalar);
|
||||||
render.push();
|
render.push();
|
||||||
|
println!("generated object");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -56,12 +65,14 @@ impl Generator for RustGenerator {
|
|||||||
let render = render.clone();
|
let render = render.clone();
|
||||||
|
|
||||||
move |t| {
|
move |t| {
|
||||||
let rendered_scalar = render_input(t)?;
|
println!("generating input");
|
||||||
|
let rendered_scalar = render_input(&common_funcs, t)?;
|
||||||
|
|
||||||
let mut render = render.lock().unwrap();
|
let mut render = render.lock().unwrap();
|
||||||
|
|
||||||
render.append(rendered_scalar);
|
render.append(rendered_scalar);
|
||||||
render.push();
|
render.push();
|
||||||
|
println!("generated input");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -70,12 +81,14 @@ impl Generator for RustGenerator {
|
|||||||
let render = render.clone();
|
let render = render.clone();
|
||||||
|
|
||||||
move |t| {
|
move |t| {
|
||||||
|
println!("generating enum");
|
||||||
let rendered_scalar = render_enum(t)?;
|
let rendered_scalar = render_enum(t)?;
|
||||||
|
|
||||||
let mut render = render.lock().unwrap();
|
let mut render = render.lock().unwrap();
|
||||||
|
|
||||||
render.append(rendered_scalar);
|
render.append(rendered_scalar);
|
||||||
render.push();
|
render.push();
|
||||||
|
println!("generated enum");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -85,6 +98,8 @@ impl Generator for RustGenerator {
|
|||||||
|
|
||||||
visitor.run()?;
|
visitor.run()?;
|
||||||
|
|
||||||
|
println!("done generating objects");
|
||||||
|
|
||||||
let rendered = render.lock().unwrap();
|
let rendered = render.lock().unwrap();
|
||||||
|
|
||||||
rendered
|
rendered
|
||||||
|
@ -1,13 +1,35 @@
|
|||||||
use dagger_core::introspection::FullType;
|
use dagger_core::introspection::{FullType, FullTypeInputFields};
|
||||||
use genco::prelude::rust;
|
use genco::prelude::rust;
|
||||||
use genco::quote;
|
use genco::quote;
|
||||||
|
|
||||||
|
use crate::functions::CommonFunctions;
|
||||||
use crate::rust::functions::format_name;
|
use crate::rust::functions::format_name;
|
||||||
|
|
||||||
pub fn render_input(t: &FullType) -> eyre::Result<rust::Tokens> {
|
pub fn render_input(funcs: &CommonFunctions, t: &FullType) -> eyre::Result<rust::Tokens> {
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
pub struct $(format_name(t.name.as_ref().unwrap())) {
|
pub struct $(format_name(t.name.as_ref().unwrap())) {
|
||||||
|
$(render_input_fields(funcs, t.input_fields.as_ref().unwrap_or(&Vec::new()) ))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn render_input_fields(
|
||||||
|
funcs: &CommonFunctions,
|
||||||
|
fields: &[FullTypeInputFields],
|
||||||
|
) -> Option<rust::Tokens> {
|
||||||
|
let rendered_fields = fields.iter().map(|f| render_input_field(funcs, f));
|
||||||
|
|
||||||
|
if rendered_fields.len() == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
$(for field in rendered_fields join ($['\r']) => $field)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn render_input_field(funcs: &CommonFunctions, field: &FullTypeInputFields) -> rust::Tokens {
|
||||||
|
quote! {
|
||||||
|
$(&field.input_value.name): $(funcs.format_input_type(&field.input_value.type_))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -1,12 +1,40 @@
|
|||||||
use dagger_core::introspection::FullType;
|
use dagger_core::introspection::{FullType, FullTypeFields};
|
||||||
use genco::prelude::rust;
|
use genco::prelude::rust;
|
||||||
use genco::quote;
|
use genco::quote;
|
||||||
|
|
||||||
use crate::rust::functions::format_name;
|
use crate::rust::functions::format_name;
|
||||||
|
use crate::utility::OptionExt;
|
||||||
|
|
||||||
pub fn render_object(t: &FullType) -> eyre::Result<rust::Tokens> {
|
pub fn render_object(t: &FullType) -> eyre::Result<rust::Tokens> {
|
||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
pub struct $(format_name(t.name.as_ref().unwrap())) {
|
pub struct $(t.name.pipe(|s| format_name(s))) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
$(t.fields.pipe(render_optional_args))
|
||||||
|
|
||||||
|
impl $(t.name.pipe(|s| format_name(s))) {
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_optional_args(fields: &Vec<FullTypeFields>) -> Option<rust::Tokens> {
|
||||||
|
let rendered_fields = fields
|
||||||
|
.iter()
|
||||||
|
.map(render_optional_arg)
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if rendered_fields.len() == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(quote! {
|
||||||
|
$(for field in rendered_fields join ($['\r']) => $field)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn render_optional_arg(field: &FullTypeFields) -> Option<rust::Tokens> {
|
||||||
|
todo!()
|
||||||
|
}
|
||||||
|
18
crates/dagger-codegen/src/utility.rs
Normal file
18
crates/dagger-codegen/src/utility.rs
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
pub trait OptionExt<'t, T: 't> {
|
||||||
|
fn pipe<U, F>(&'t self, f: F) -> Option<U>
|
||||||
|
where
|
||||||
|
F: FnOnce(&'t T) -> U;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'t, T: 't> OptionExt<'t, T> for Option<T> {
|
||||||
|
#[inline]
|
||||||
|
fn pipe<U, F>(&'t self, f: F) -> Option<U>
|
||||||
|
where
|
||||||
|
F: FnOnce(&'t T) -> U,
|
||||||
|
{
|
||||||
|
match *self {
|
||||||
|
Some(ref x) => Some(f(x)),
|
||||||
|
None => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user