fix add_fields population

This commit is contained in:
Sandipsinh Rathod 2024-12-22 13:40:47 -05:00
parent 5eeb1b6002
commit 42cbcf1c7b
14 changed files with 652 additions and 28 deletions

10
Cargo.lock generated

@ -185,6 +185,7 @@ dependencies = [
"base64",
"convert_case",
"lazy_static",
"macros",
"oapi",
"oas3",
"openapi3-parser",
@ -521,6 +522,15 @@ dependencies = [
"logos-codegen",
]
[[package]]
name = "macros"
version = "0.1.0"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.90",
]
[[package]]
name = "memchr"
version = "2.7.4"

@ -21,3 +21,7 @@ wit-parser = "0.222.0"
lazy_static = "1.5.0"
base64 = "0.22.1"
strum_macros = "0.26.4"
macros = {path = "macros"}
[workspace]
members = [".", "macros"]

7
macros/Cargo.lock generated Normal file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "macros"
version = "0.1.0"

12
macros/Cargo.toml Normal file

@ -0,0 +1,12 @@
[package]
name = "macros"
version = "0.1.0"
edition = "2021"
[lib]
proc-macro = true
[dependencies]
syn = { version = "2.0.60", features = ["derive", "full"] }
quote = "1.0.36"
proc-macro2 = "1.0.81"

9
macros/src/lib.rs Normal file

@ -0,0 +1,9 @@
use proc_macro::TokenStream;
mod merge_right;
use crate::merge_right::expand_merge_right_derive;
#[proc_macro_derive(MergeRight, attributes(merge_right))]
pub fn merge_right_derive(input: TokenStream) -> TokenStream {
expand_merge_right_derive(input)
}

186
macros/src/merge_right.rs Normal file

@ -0,0 +1,186 @@
extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::spanned::Spanned;
use syn::{parse_macro_input, Data, DeriveInput, Fields, Index};
const MERGE_RIGHT_FN: &str = "merge_right_fn";
const MERGE_RIGHT: &str = "merge_right";
#[derive(Default)]
struct Attrs {
merge_right_fn: Option<syn::ExprPath>,
}
fn get_attrs(attrs: &[syn::Attribute]) -> syn::Result<Attrs> {
let mut attrs_ret = Attrs::default();
for attr in attrs {
if attr.path().is_ident(MERGE_RIGHT) {
attr.parse_nested_meta(|meta| {
if meta.path.is_ident(MERGE_RIGHT_FN) {
let p: syn::Expr = meta.value()?.parse()?;
let lit =
if let syn::Expr::Lit(syn::ExprLit { lit: syn::Lit::Str(lit), .. }) = p {
let suffix = lit.suffix();
if !suffix.is_empty() {
return Err(syn::Error::new(
lit.span(),
format!("unexpected suffix `{}` on string literal", suffix),
));
}
lit
} else {
return Err(syn::Error::new(
p.span(),
format!(
"expected merge_right {} attribute to be a string.",
MERGE_RIGHT_FN
),
));
};
let expr_path: syn::ExprPath = lit.parse()?;
attrs_ret.merge_right_fn = Some(expr_path);
Ok(())
} else {
Err(syn::Error::new(attr.span(), "Unknown helper attribute."))
}
})?;
}
}
Ok(attrs_ret)
}
pub fn expand_merge_right_derive(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
let name = input.ident.clone();
let generics = input.generics.clone();
let gen = match input.data {
// Implement for structs
Data::Struct(data) => {
let fields = match &data.fields {
Fields::Named(fields) => &fields.named,
Fields::Unnamed(fields) => &fields.unnamed,
Fields::Unit => {
return quote! {
impl crate::merge_right::MergeRight for #name {
fn merge_right(self, other: Self) -> Self {
other
}
}
}
.into()
}
};
let merge_logic = fields.iter().enumerate().map(|(i, f)| {
let attrs = get_attrs(&f.attrs);
if let Err(err) = attrs {
panic!("{}", err);
}
let attrs = attrs.unwrap();
let name = &f.ident;
match &data.fields {
Fields::Named(_) => {
if let Some(merge_right_fn) = attrs.merge_right_fn {
quote! {
#name: #merge_right_fn(self.#name, other.#name),
}
} else {
quote! {
#name: self.#name.merge_right(other.#name),
}
}
}
Fields::Unnamed(_) => {
let name = Index::from(i);
if let Some(merge_right_fn) = attrs.merge_right_fn {
quote! {
#merge_right_fn(self.#name, other.#name),
}
} else {
quote! {
self.#name.merge_right(other.#name),
}
}
}
Fields::Unit => unreachable!(),
}
});
let generics_lt = generics.lt_token;
let generics_gt = generics.gt_token;
let generics_params = generics.params;
let generics_del = quote! {
#generics_lt #generics_params #generics_gt
};
let initializer = match data.fields {
Fields::Named(_) => quote! {
Self {
#(#merge_logic)*
}
},
Fields::Unnamed(_) => quote! {
Self(#(#merge_logic)*)
},
Fields::Unit => unreachable!(),
};
quote! {
impl #generics_del crate::merge_right::MergeRight for #name #generics_del {
fn merge_right(self, other: Self) -> Self {
#initializer
}
}
}
}
// Implement for enums
Data::Enum(_) => quote! {
impl crate::merge_right::MergeRight for #name {
fn merge_right(self, other: Self) -> Self {
other
}
}
},
// Optionally handle or disallow unions
Data::Union(_) => {
return syn::Error::new_spanned(input, "Union types are not supported by MergeRight")
.to_compile_error()
.into()
}
};
gen.into()
}
#[cfg(test)]
mod tests {
use syn::{parse_quote, Attribute};
use super::*;
#[test]
fn test_get_attrs_invalid_type() {
let attrs: Vec<Attribute> = vec![parse_quote!(#[merge_right(merge_right_fn = 123)])];
let result = get_attrs(&attrs);
assert!(
result.is_err(),
"Expected error with non-string type for `merge_right_fn`"
);
}
#[test]
fn test_get_attrs_unexpected_suffix() {
let attrs: Vec<Attribute> =
vec![parse_quote!(#[merge_right(merge_right_fn = "some_fn()")])];
let result = get_attrs(&attrs);
assert!(
result.is_err(),
"Expected error with unexpected suffix on string literal"
);
}
}

@ -1,13 +1,16 @@
use std::collections::BTreeSet;
use serde::{Deserialize, Serialize};
use macros::MergeRight;
use crate::config::wit_types::WitType;
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Config {
pub package: String,
pub interfaces: Vec<Interface>,
pub interfaces: BTreeSet<Interface>,
pub world: World,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct World {
pub name: String,
pub uses: Vec<UseStatement>,
@ -15,47 +18,84 @@ pub struct World {
pub exports: Vec<Interface>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Interface {
pub name: String,
pub records: Vec<Record>,
pub records: BTreeSet<Record>,
pub uses: Vec<UseStatement>,
pub functions: Vec<Function>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
impl PartialOrd for Interface {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name.cmp(&other.name))
}
}
impl Ord for Interface {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Record {
pub name: String,
pub fields: Vec<Field>,
pub added_fields: Vec<Field>,
pub fields: BTreeSet<Field>,
pub added_fields: BTreeSet<Field>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
impl PartialOrd for Record {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name.cmp(&other.name))
}
}
impl Ord for Record {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct UseStatement {
pub name: String,
pub items: Vec<String>,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Function {
pub name: String,
pub parameters: Vec<Parameter>,
pub return_type: ReturnTy,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct ReturnTy {
pub return_type: String,
pub error_type: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Parameter {
pub name: String,
pub parameter_type: String,
}
#[derive(Debug, Clone, Default, PartialEq, Eq)]
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight)]
pub struct Field {
pub name: String,
pub field_type: WitType,
}
impl PartialOrd for Field {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.name.cmp(&other.name))
}
}
impl Ord for Field {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.name.cmp(&other.name)
}
}

@ -1,7 +1,9 @@
use std::collections::BTreeSet;
use base64::Engine;
use tailcall_valid::{Valid, Validator};
use crate::config::config::{Config, Field, Interface, Record};
use crate::config::wit_types::WitType;
use crate::merge_right::MergeRight;
use crate::tryfold::TryFold;
pub fn fix_args(config: Config) -> Valid<Config, anyhow::Error, anyhow::Error> {
@ -14,16 +16,22 @@ pub fn fix_args(config: Config) -> Valid<Config, anyhow::Error, anyhow::Error> {
fix_field()
.try_fold(&(&config, interface, record, &field, &field.field_type), interface.clone())
.and_then(|new_interface| {
Valid::succeed(new_interface)
Valid::succeed(Some(new_interface))
})
} else {
Valid::succeed(interface.clone())
Valid::succeed(None)
}
})
})
}).and_then(|x| {
let x = x.into_iter().flatten().into_iter().flatten().collect::<Vec<_>>();
config.interfaces = x;
let x = x.into_iter().flatten().into_iter().flatten().filter_map(|x| x).collect::<Vec<_>>();
let mut map = BTreeSet::new();
for interface in x {
map.insert(interface);
}
config.interfaces = config.interfaces.merge_right(map);
Valid::succeed(config)
})
@ -39,7 +47,7 @@ fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Fi
WitType::Result(a, b) => {
// TODO: this impl needs check.
// eg: -> result<record A {}, record B {}>
// this does not make sense to resolve with rec.name-field.name-A/B
// this does not make sense to resolve with rec.name-A/B
return if !a.is_primitive() {
fix_field().try_fold(&(*config, *interface, *rec, *field, a), o)
@ -61,7 +69,26 @@ fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Fi
})));
}
WitType::Record(records) => {
for (arg_name, ty) in records {
let field_name = if field.name.is_empty() {
base64::prelude::BASE64_STANDARD.encode(field.name.as_bytes())
}else {
field.name.clone()
};
let name = format!("{}-{}", rec.name, field_name);
let new_field = Field {
name,
field_type: WitType::Record(records.clone()),
};
let mut rec = (*rec).clone();
rec.added_fields.insert(new_field);
// let mut filtered_records = o.records.into_iter().filter(|r| r.name == rec.name).collect::<Vec<_>>();
// filtered_records.push(rec);
o.records.remove(&rec);
o.records.insert(rec);
Valid::succeed(o)
/* for (arg_name, ty) in records {
let arg_name = if arg_name.is_empty() {
// TODO: maybe we can introduce some transformers
// which uses AI to generate better names
@ -71,8 +98,9 @@ fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Fi
};
let name = format!("{}-{}-{}", rec.name, field.name, arg_name);
println!("name: {}", name);
let new_field = Field {
name,
name: name.clone(),
field_type: ty.clone(),
};
let mut rec = (*rec).clone();
@ -80,9 +108,10 @@ fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Fi
let mut filtered_records = o.records.into_iter().filter(|r| r.name == rec.name).collect::<Vec<_>>();
filtered_records.push(rec);
o.records = filtered_records;
}
Valid::succeed(o)
Valid::succeed(o)*/
/* Valid::from_iter(records.iter(), |(_, b)| {
fix_field()

@ -1,3 +1,4 @@
use std::collections::BTreeSet;
use anyhow::{anyhow, Error};
use tailcall_valid::{Valid, Validator};
use crate::config::config::{Config, Field, Interface, Record};
@ -28,8 +29,8 @@ pub fn handle_types(config: Config, spec: &OpenApiSpec) -> Valid<Config, Error,
.and_then(|fields| {
let record = Record {
name: record_name.clone(),
fields,
added_fields: vec![],
fields: fields.into_iter().collect::<BTreeSet<_>>(),
added_fields: Default::default(),
};
Valid::succeed(record)
})
@ -37,10 +38,10 @@ pub fn handle_types(config: Config, spec: &OpenApiSpec) -> Valid<Config, Error,
}).and_then(|records| {
let interface = Interface {
name: "types".to_string(),
records,
records: records.into_iter().collect::<BTreeSet<_>>(),
..Default::default()
};
config.interfaces.push(interface);
config.interfaces.insert(interface);
Valid::succeed(())
})
}).and_then(|_| Valid::succeed(config))

@ -1,9 +1,10 @@
use serde::{Deserialize, Serialize};
use tailcall_valid::{Valid, Validator};
use crate::config::to_wit::ToWit;
use crate::ser::{OpenApiSpec, Schema};
#[derive(Debug, Clone, Default, PartialEq, Eq, strum_macros::Display)]
#[derive(Debug, Clone, Default, PartialEq, Eq, strum_macros::Display, Serialize, Deserialize)]
pub enum WitType {
// Primitive Types
Bool,

@ -5,6 +5,8 @@ mod config;
mod transformer;
mod transform;
mod tryfold;
mod merge_right;
mod primitive;
use serde_json::{Map, Value};
use anyhow::{Result, bail};

293
src/merge_right.rs Normal file

@ -0,0 +1,293 @@
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use crate::config::wit_types::WitType;
pub trait MergeRight {
fn merge_right(self, other: Self) -> Self;
}
impl<A: MergeRight> MergeRight for Option<A> {
fn merge_right(self, other: Self) -> Self {
match (self, other) {
(Some(this), Some(that)) => Some(this.merge_right(that)),
(None, Some(that)) => Some(that),
(Some(this), None) => Some(this),
(None, None) => None,
}
}
}
impl<A> MergeRight for Vec<A> {
fn merge_right(mut self, other: Self) -> Self {
self.extend(other);
self
}
}
impl<V> MergeRight for BTreeSet<V>
where
V: Ord,
{
fn merge_right(self, mut other: Self) -> Self {
other.extend(self);
other
}
}
impl<V> MergeRight for HashSet<V>
where
V: Eq + std::hash::Hash,
{
fn merge_right(mut self, other: Self) -> Self {
self.extend(other);
self
}
}
impl<K, V> MergeRight for BTreeMap<K, V>
where
K: Ord,
V: MergeRight,
{
fn merge_right(mut self, other: Self) -> Self {
for (other_name, mut other_value) in other {
if let Some(self_value) = self.remove(&other_name) {
other_value = self_value.merge_right(other_value);
}
self.insert(other_name, other_value);
}
self
}
}
impl<K, V> MergeRight for HashMap<K, V>
where
K: Eq + std::hash::Hash,
V: MergeRight,
{
fn merge_right(mut self, other: Self) -> Self {
for (other_name, mut other_value) in other {
if let Some(self_value) = self.remove(&other_name) {
other_value = self_value.merge_right(other_value);
}
self.insert(other_name, other_value);
}
self
}
}
impl MergeRight for WitType {
fn merge_right(self, other: Self) -> Self {
other
}
}
#[cfg(test)]
mod tests {
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
use serde_json::json;
use super::MergeRight;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
struct Test(u32);
impl From<u32> for Test {
fn from(value: u32) -> Self {
Self(value)
}
}
impl MergeRight for Test {
fn merge_right(self, other: Self) -> Self {
Self(self.0 + other.0)
}
}
#[test]
fn test_option() {
let x: Option<Test> = None.merge_right(None);
assert_eq!(x, None);
let x = Some(Test::from(1)).merge_right(None);
assert_eq!(x, Some(Test::from(1)));
let x = None.merge_right(Some(Test::from(2)));
assert_eq!(x, Some(Test::from(2)));
let x = Some(Test::from(1)).merge_right(Some(Test::from(2)));
assert_eq!(x, Some(Test::from(3)));
}
#[test]
fn test_vec() {
let l: Vec<Test> = vec![];
let r: Vec<Test> = vec![];
assert_eq!(l.merge_right(r), vec![]);
let l: Vec<Test> = vec![Test::from(1), Test::from(2)];
let r: Vec<Test> = vec![];
assert_eq!(l.merge_right(r), vec![Test::from(1), Test::from(2)]);
let l: Vec<Test> = vec![];
let r: Vec<Test> = vec![Test::from(3), Test::from(4)];
assert_eq!(l.merge_right(r), vec![Test::from(3), Test::from(4)]);
let l: Vec<Test> = vec![Test::from(1), Test::from(2)];
let r: Vec<Test> = vec![Test::from(3), Test::from(4)];
assert_eq!(
l.merge_right(r),
vec![Test::from(1), Test::from(2), Test::from(3), Test::from(4)]
);
}
#[test]
fn test_btree_set() {
let l: BTreeSet<Test> = BTreeSet::from_iter(vec![]);
let r: BTreeSet<Test> = BTreeSet::from_iter(vec![]);
assert_eq!(l.merge_right(r), BTreeSet::from_iter(vec![]));
let l: BTreeSet<Test> = BTreeSet::from_iter(vec![Test::from(1), Test::from(2)]);
let r: BTreeSet<Test> = BTreeSet::from_iter(vec![]);
assert_eq!(
l.merge_right(r),
BTreeSet::from_iter(vec![Test::from(1), Test::from(2)])
);
let l: BTreeSet<Test> = BTreeSet::from_iter(vec![]);
let r: BTreeSet<Test> = BTreeSet::from_iter(vec![Test::from(3), Test::from(4)]);
assert_eq!(
l.merge_right(r),
BTreeSet::from_iter(vec![Test::from(3), Test::from(4)])
);
let l: BTreeSet<Test> = BTreeSet::from_iter(vec![Test::from(1), Test::from(2)]);
let r: BTreeSet<Test> =
BTreeSet::from_iter(vec![Test::from(2), Test::from(3), Test::from(4)]);
assert_eq!(
l.merge_right(r),
BTreeSet::from_iter(vec![
Test::from(1),
Test::from(2),
Test::from(3),
Test::from(4)
])
);
}
#[test]
fn test_hash_set() {
let l: HashSet<Test> = HashSet::from_iter(vec![]);
let r: HashSet<Test> = HashSet::from_iter(vec![]);
assert_eq!(l.merge_right(r), HashSet::from_iter(vec![]));
let l: HashSet<Test> = HashSet::from_iter(vec![Test::from(1), Test::from(2)]);
let r: HashSet<Test> = HashSet::from_iter(vec![]);
assert_eq!(
l.merge_right(r),
HashSet::from_iter(vec![Test::from(1), Test::from(2)])
);
let l: HashSet<Test> = HashSet::from_iter(vec![]);
let r: HashSet<Test> = HashSet::from_iter(vec![Test::from(3), Test::from(4)]);
assert_eq!(
l.merge_right(r),
HashSet::from_iter(vec![Test::from(3), Test::from(4)])
);
let l: HashSet<Test> = HashSet::from_iter(vec![Test::from(1), Test::from(2)]);
let r: HashSet<Test> =
HashSet::from_iter(vec![Test::from(2), Test::from(3), Test::from(4)]);
assert_eq!(
l.merge_right(r),
HashSet::from_iter(vec![
Test::from(1),
Test::from(2),
Test::from(3),
Test::from(4)
])
);
}
#[test]
fn test_btree_map() {
let l: BTreeMap<u32, Test> = BTreeMap::from_iter(vec![]);
let r: BTreeMap<u32, Test> = BTreeMap::from_iter(vec![]);
assert_eq!(l.merge_right(r), BTreeMap::from_iter(vec![]));
let l: BTreeMap<u32, Test> =
BTreeMap::from_iter(vec![(1, Test::from(1)), (2, Test::from(2))]);
let r: BTreeMap<u32, Test> = BTreeMap::from_iter(vec![]);
assert_eq!(
l.merge_right(r),
BTreeMap::from_iter(vec![(1, Test::from(1)), (2, Test::from(2))])
);
let l: BTreeMap<u32, Test> = BTreeMap::from_iter(vec![]);
let r: BTreeMap<u32, Test> =
BTreeMap::from_iter(vec![(3, Test::from(3)), (4, Test::from(4))]);
assert_eq!(
l.merge_right(r),
BTreeMap::from_iter(vec![(3, Test::from(3)), (4, Test::from(4))])
);
let l: BTreeMap<u32, Test> =
BTreeMap::from_iter(vec![(1, Test::from(1)), (2, Test::from(2))]);
let r: BTreeMap<u32, Test> = BTreeMap::from_iter(vec![
(2, Test::from(5)),
(3, Test::from(3)),
(4, Test::from(4)),
]);
assert_eq!(
l.merge_right(r),
BTreeMap::from_iter(vec![
(1, Test::from(1)),
(2, Test::from(7)),
(3, Test::from(3)),
(4, Test::from(4))
])
);
}
#[test]
fn test_hash_map() {
let l: HashMap<u32, Test> = HashMap::from_iter(vec![]);
let r: HashMap<u32, Test> = HashMap::from_iter(vec![]);
assert_eq!(l.merge_right(r), HashMap::from_iter(vec![]));
let l: HashMap<u32, Test> =
HashMap::from_iter(vec![(1, Test::from(1)), (2, Test::from(2))]);
let r: HashMap<u32, Test> = HashMap::from_iter(vec![]);
assert_eq!(
l.merge_right(r),
HashMap::from_iter(vec![(1, Test::from(1)), (2, Test::from(2))])
);
let l: HashMap<u32, Test> = HashMap::from_iter(vec![]);
let r: HashMap<u32, Test> =
HashMap::from_iter(vec![(3, Test::from(3)), (4, Test::from(4))]);
assert_eq!(
l.merge_right(r),
HashMap::from_iter(vec![(3, Test::from(3)), (4, Test::from(4))])
);
let l: HashMap<u32, Test> =
HashMap::from_iter(vec![(1, Test::from(1)), (2, Test::from(2))]);
let r: HashMap<u32, Test> = HashMap::from_iter(vec![
(2, Test::from(5)),
(3, Test::from(3)),
(4, Test::from(4)),
]);
assert_eq!(
l.merge_right(r),
HashMap::from_iter(vec![
(1, Test::from(1)),
(2, Test::from(7)),
(3, Test::from(3)),
(4, Test::from(4))
])
);
}
}

29
src/primitive.rs Normal file

@ -0,0 +1,29 @@
use std::marker::PhantomData;
use std::num::NonZeroU64;
use crate::merge_right::MergeRight;
pub trait Primitive {}
impl Primitive for bool {}
impl Primitive for char {}
impl Primitive for f32 {}
impl Primitive for f64 {}
impl Primitive for i16 {}
impl Primitive for i32 {}
impl Primitive for i64 {}
impl Primitive for i8 {}
impl Primitive for NonZeroU64 {}
impl Primitive for String {}
impl Primitive for u16 {}
impl Primitive for u32 {}
impl Primitive for u64 {}
impl Primitive for u8 {}
impl Primitive for usize {}
impl<A> Primitive for PhantomData<A> {}
impl<A: Primitive> MergeRight for A {
fn merge_right(self, other: Self) -> Self {
other
}
}

@ -29,8 +29,9 @@ mod t {
let mut res = to_config(y).to_result();
match res.as_mut() {
Ok(v) => {
v.package = "api:todos@1.0.0".to_string();
println!("{}", v.to_wit());
println!("{}", serde_json::to_string_pretty(v).unwrap());
// v.package = "api:todos@1.0.0".to_string();
// println!("{}", v.to_wit());
// let mut resolve = Resolve::new();
// resolve.push_str("foox.wit", &v.to_wit()).expect("TODO: panic message`");
// println!("{:#?}", resolve);