partial: prototyping proto -> wit
This commit is contained in:
parent
c4ceb92e11
commit
1b1a70f5e1
@ -1,145 +0,0 @@
|
||||
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> {
|
||||
Valid::succeed(config)
|
||||
.and_then(|mut config| {
|
||||
Valid::from_iter(config.interfaces.iter().cloned().collect::<Vec<_>>(), |mut interface| {
|
||||
Valid::from_iter(interface.records.iter().cloned(), |mut record| {
|
||||
Valid::from_iter(record.fields.iter().cloned(), |field| {
|
||||
if !field.field_type.is_kind_of_primitive() {
|
||||
fix_field()
|
||||
.try_fold(&(&config, &interface, &record, &field, &field.field_type), Field::default())
|
||||
.and_then(|field| {
|
||||
Valid::succeed(Some(field))
|
||||
})
|
||||
}else {
|
||||
Valid::succeed(None)
|
||||
}
|
||||
}).and_then(|v| {
|
||||
let fields = v.into_iter().filter_map(|x| x).collect();
|
||||
record.added_fields = fields;
|
||||
|
||||
Valid::succeed(record)
|
||||
})
|
||||
}).and_then(|records| {
|
||||
interface.records = records.into_iter().collect();
|
||||
Valid::succeed(interface)
|
||||
})
|
||||
}).and_then(|interfaces| {
|
||||
config.interfaces = interfaces.into_iter().collect();
|
||||
/*for interface in interfaces {
|
||||
if let Some(interface) = config.interfaces.iter().find(|i| i.name == interface.name) {
|
||||
for record in interface.records {
|
||||
if let Some(mut record) = interface.records.iter().find(|r| r.name == record.name).cloned() {
|
||||
for field in record.fields {
|
||||
if let Some(field) = record.fields.iter().find(|f| f.name == field.name) {
|
||||
let mut new_field = field.clone();
|
||||
new_field.field_type = field.field_type.clone().merge_right(new_field.field_type.clone());
|
||||
record.fields.remove(&field);
|
||||
record.fields.insert(new_field);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}else {
|
||||
config.interfaces.insert(interface);
|
||||
}
|
||||
}*/
|
||||
/* let mut new_interfaces = BTreeSet::new();
|
||||
for mut interface in config.interfaces {
|
||||
let mut new_records = BTreeSet::new();
|
||||
for mut record in interface.records {
|
||||
let mut new_fields = BTreeSet::new();
|
||||
for mut field in record.fields {
|
||||
let mut new_field = interfaces
|
||||
.iter()
|
||||
.find(|i| i.name == interface.name).and_then(|interface| interface.records.iter().find(|r| r.name == record.name).and_then(|record|record.fields.iter().find(|f| f.name == field.name)))
|
||||
.unwrap_or(&field)
|
||||
.clone();
|
||||
|
||||
new_field = new_field.merge_right(field);
|
||||
new_fields.insert(new_field);
|
||||
}
|
||||
record.fields = new_fields;
|
||||
new_records.insert(record);
|
||||
}
|
||||
interface.records = new_records;
|
||||
new_interfaces.insert(interface);
|
||||
}
|
||||
|
||||
config.interfaces = new_interfaces;*/
|
||||
// config.interfaces = config.interfaces.merge_right(map);
|
||||
|
||||
Valid::succeed(config)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
interface types {
|
||||
|
||||
record error { error: { message: string, details: list<{ field: string, message: string }>, code: string } }
|
||||
record todo { completed: bool, created-at: string, description: string, due-date: string, id: string, title: string, updated-at: string, user-id: string }
|
||||
record todo-create { description: string, due-date: string, title: string, user-id: string }
|
||||
record todo-list { data: list<{ id: string, user-id: string, title: string, due-date: string, created-at: string, updated-at: string, completed: bool, description: string }>, metadata: { total: s32, offset: s32, limit: s32 } }
|
||||
record todo-response { data: { id: string, user-id: string, title: string, due-date: string, created-at: string, updated-at: string, completed: bool, description: string } }
|
||||
record todo-update { completed: bool, description: string, due-date: string, title: string }
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
fn fix_field<'a>() -> TryFold<'a, (&'a Config, &'a Interface, &'a Record, &'a Field, &'a WitType), Field, anyhow::Error> {
|
||||
TryFold::<(&Config, &Interface, &Record, &Field, &WitType), Field, anyhow::Error>::new(move |(config, interface, rec, field, wit), o| {
|
||||
match &wit {
|
||||
WitType::Option(x) => {
|
||||
return fix_field().try_fold(&(*config, *interface, *rec, *field, x), o);
|
||||
}
|
||||
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-A/B
|
||||
|
||||
return if !a.is_primitive() {
|
||||
fix_field().try_fold(&(*config, *interface, *rec, *field, a), o)
|
||||
} else if !b.is_primitive() {
|
||||
fix_field().try_fold(&(*config, *interface, *rec, *field, b), o)
|
||||
} else {
|
||||
// TODO: Fix the possible conflicts here
|
||||
fix_field().try_fold(&(*config, *interface, *rec, *field, a), o)
|
||||
.and_then(|new_interface| fix_field().try_fold(&(*config, *interface, *rec, *field, b), new_interface))
|
||||
};
|
||||
}
|
||||
WitType::List(x) => fix_field().try_fold(&(*config, *interface, *rec, *field, x.as_ref()), o),
|
||||
WitType::Tuple(x) => {
|
||||
// TODO: Fix the possible conflicts here
|
||||
return Valid::from_iter(x.iter(), |x| fix_field().try_fold(&(*config, *interface, *rec, *field, x), o.clone()))
|
||||
.and_then(|v| Valid::succeed(v.into_iter().fold((*field).clone(), |a, b| {
|
||||
a.merge_right(b)
|
||||
})));
|
||||
}
|
||||
WitType::Record(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()),
|
||||
};
|
||||
Valid::succeed(new_field)
|
||||
}
|
||||
WitType::FieldTy(_) => Valid::succeed(o),
|
||||
// Ideally this case should never happen,
|
||||
// but we should always throw an error to avoid infinite recursion
|
||||
_ => return Valid::fail(anyhow::anyhow!("Unknown type: {:?}", field.field_type)),
|
||||
}
|
||||
})
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
pub mod config;
|
||||
pub mod wit_types;
|
||||
pub mod to_wit;
|
||||
pub mod fixargs;
|
||||
pub mod handle_files;
|
||||
|
@ -40,26 +40,6 @@ pub enum WitType {
|
||||
}
|
||||
|
||||
impl WitType {
|
||||
pub fn is_primitive(&self) -> bool {
|
||||
match self {
|
||||
WitType::Bool | WitType::U8 | WitType::U16 | WitType::U32 | WitType::U64 | WitType::S8 | WitType::S16 | WitType::S32 | WitType::S64 | WitType::Float32 | WitType::Float64 | WitType::Char | WitType::String => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn is_kind_of_primitive(&self) -> bool {
|
||||
match self {
|
||||
WitType::Option(x) => x.is_primitive(),
|
||||
WitType::Result(a, b) => a.is_primitive() && b.is_primitive(),
|
||||
WitType::List(x) => x.is_primitive(),
|
||||
WitType::Tuple(x) => x.iter().all(|x| x.is_primitive()),
|
||||
WitType::Variant(_) => true,
|
||||
WitType::Enum(_) => true,
|
||||
WitType::Flags(_) => true,
|
||||
WitType::Handle(_) => true,
|
||||
WitType::TypeAlias(_, _) => true,
|
||||
v => v.is_primitive(),
|
||||
}
|
||||
}
|
||||
pub fn from_schema(
|
||||
schema: &Schema,
|
||||
openapi: &OpenApiSpec<Resolved>,
|
||||
|
@ -12,6 +12,7 @@ mod transform;
|
||||
mod tryfold;
|
||||
mod merge_right;
|
||||
mod primitive;
|
||||
mod proto;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct WIPValue(Value);
|
||||
|
@ -1,2 +1,3 @@
|
||||
pub mod openapi_spec;
|
||||
pub mod openapi;
|
||||
pub mod openapi;
|
||||
pub(super) mod handle_files;
|
||||
|
@ -4,9 +4,8 @@ use anyhow::Error;
|
||||
use convert_case::{Case, Casing};
|
||||
use schemars::JsonSchema;
|
||||
use tailcall_valid::{Valid, Validator};
|
||||
use crate::config::fixargs::fix_args;
|
||||
use crate::config::handle_files::handle_types;
|
||||
use crate::config::config::Config;
|
||||
use crate::openapi::handle_files::handle_types;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Unresolved;
|
||||
@ -250,7 +249,6 @@ impl OpenApiSpec<Resolved> {
|
||||
pub fn to_config(&self) -> Valid<Config, Error, Error> {
|
||||
Valid::succeed(Config::default())
|
||||
.and_then(|config| handle_types(config, &self))
|
||||
.and_then(|config| fix_args(config))
|
||||
}
|
||||
}
|
||||
|
||||
|
45
src/proto/handle_types.rs
Normal file
45
src/proto/handle_types.rs
Normal file
@ -0,0 +1,45 @@
|
||||
use std::collections::BTreeSet;
|
||||
use oas3::spec::ParameterIn::Path;
|
||||
use protox::prost_reflect::prost_types::{field_descriptor_proto, FileDescriptorProto, FileDescriptorSet};
|
||||
use tailcall_valid::{Valid, Validator};
|
||||
use crate::config::config::{Config, Field, Interface, Record};
|
||||
use crate::config::wit_types::WitType;
|
||||
|
||||
fn append_enums(config: &Config, file: &FileDescriptorProto) -> Valid<Record, anyhow::Error, anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
fn append_message(config: &Config, file: &FileDescriptorProto) -> Valid<Record, anyhow::Error, anyhow::Error> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn handle_types(config: Config, proto: &[FileDescriptorSet], package: String) -> Valid<Config, anyhow::Error, anyhow::Error> {
|
||||
Valid::succeed(config)
|
||||
.and_then(|config| {
|
||||
Valid::from_iter(proto.iter(), |set| {
|
||||
Valid::from_iter(set.file.iter(), |file| {
|
||||
append_enums(&config, file).and_then(|rec| {
|
||||
append_message(&config, file)
|
||||
.and_then(|mut new_rec| {
|
||||
new_rec.fields.extend(rec.fields);
|
||||
Valid::succeed(new_rec)
|
||||
})
|
||||
})
|
||||
})
|
||||
.and_then(|v| {
|
||||
Valid::succeed(Interface {
|
||||
name: "type".to_string(),
|
||||
records: v.into_iter().collect(),
|
||||
uses: vec![],
|
||||
functions: vec![],
|
||||
})
|
||||
})
|
||||
})
|
||||
}).and_then(|v| {
|
||||
Valid::succeed(Config {
|
||||
package,
|
||||
interfaces: v.into_iter().collect(),
|
||||
world: Default::default(),
|
||||
})
|
||||
})
|
||||
}
|
2
src/proto/mod.rs
Normal file
2
src/proto/mod.rs
Normal file
@ -0,0 +1,2 @@
|
||||
mod proto;
|
||||
mod handle_types;
|
16
src/proto/proto.rs
Normal file
16
src/proto/proto.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use protox::prost_reflect::prost_types::FileDescriptorSet;
|
||||
use tailcall_valid::{Valid, Validator};
|
||||
use crate::config::config::Config;
|
||||
use crate::proto::handle_types::handle_types;
|
||||
|
||||
pub struct Proto(Vec<FileDescriptorSet>);
|
||||
|
||||
impl Proto {
|
||||
pub fn new<T: IntoIterator<Item=FileDescriptorSet>>(v: T) -> Self {
|
||||
Self(v.into_iter().collect())
|
||||
}
|
||||
pub fn to_config(&self) -> Valid<Config, anyhow::Error, anyhow::Error> {
|
||||
Valid::succeed(Config::default())
|
||||
.and_then(|config| handle_types(config, &self.0))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user