proto -> wit: add enum/variant support (partial)

This commit is contained in:
Sandipsinh Rathod 2024-12-22 18:23:35 -05:00
parent 1b1a70f5e1
commit 5801f4e724
5 changed files with 79 additions and 31 deletions

@ -4,6 +4,11 @@ package core.todo.v1;
message TodoListRequest {string user_id = 1;}
enum Error {
UNKNOWN = 0;
NOT_FOUND = 1;
}
message TodoAddRequest {
string user_id = 1;
string task = 2;

@ -1,4 +1,4 @@
use std::collections::BTreeSet;
use std::collections::{BTreeMap, BTreeSet};
use serde::{Deserialize, Serialize};
use macros::MergeRight;
use crate::config::wit_types::WitType;
@ -21,6 +21,7 @@ pub struct World {
#[derive(Debug, Clone, Default, PartialEq, Eq, Serialize, Deserialize, MergeRight, derive_setters::Setters)]
pub struct Interface {
pub name: String,
pub varients: BTreeMap<String, WitType>,
pub records: BTreeSet<Record>,
pub uses: Vec<UseStatement>,
pub functions: Vec<Function>,

@ -105,6 +105,13 @@ impl Interface {
.collect::<Vec<String>>()
.join("\n ");
let varients = self
.varients
.iter()
.map(|(name, ty)| format!("{}", ty.to_wit(Some(generate_wit_name(name)))))
.collect::<Vec<String>>()
.join(", ");
let functions = self
.functions
.iter()
@ -113,10 +120,11 @@ impl Interface {
.join("\n ");
format!(
"interface {} {{\n {}\n {}\n {}\n}}",
"interface {} {{\n {}\n {}\n {}\n {}\n}}",
generate_wit_name(&self.name),
uses,
records,
varients,
functions
)
}
@ -140,7 +148,7 @@ impl Field {
format!(
"{}: {}",
generate_wit_name(&self.name),
self.field_type.to_wit()
self.field_type.to_wit(None)
)
}
}
@ -209,7 +217,7 @@ impl UseStatement {
}
impl WitType {
pub fn to_wit(&self) -> String {
pub fn to_wit(&self, name: Option<String>) -> String {
match self {
WitType::Bool => "bool".to_string(),
WitType::U8 => "u8".to_string(),
@ -224,28 +232,30 @@ impl WitType {
WitType::Float64 => "float64".to_string(),
WitType::Char => "char".to_string(),
WitType::String => "string".to_string(),
WitType::Option(inner) => format!("option<{}>", inner.to_wit()),
WitType::Result(ok, err) => format!("result<{}, {}>", ok.to_wit(), err.to_wit()),
WitType::List(inner) => format!("list<{}>", inner.to_wit()),
WitType::Option(inner) => format!("option<{}>", inner.to_wit(None)),
WitType::Result(ok, err) => format!("result<{}, {}>", ok.to_wit(None), err.to_wit(None)),
WitType::List(inner) => format!("list<{}>", inner.to_wit(None)),
WitType::Tuple(elements) => format!(
"tuple<{}>",
elements.iter().map(|e| e.to_wit()).collect::<Vec<_>>().join(", ")
elements.iter().map(|e| e.to_wit(None)).collect::<Vec<_>>().join(", ")
),
WitType::Record(fields) => format!(
"{{ {} }}",
"enum {} {{ {} }}",
name.unwrap_or_default(),
fields
.iter()
.map(|(name, ty)| format!("{}: {}", generate_wit_name(name), ty.to_wit()))
.map(|(name, ty)| format!("{}: {}", generate_wit_name(name), ty.to_wit(None)))
.collect::<Vec<_>>()
.join(", ")
),
WitType::Variant(variants) => format!(
"variant {{ {} }}",
"variant {} {{ {} }}",
name.unwrap_or_default(),
variants
.iter()
.map(|(name, ty)| {
if let Some(ty) = ty {
format!("{}: {}", generate_wit_name(name), ty.to_wit())
format!("{}: {}", generate_wit_name(name), ty.to_wit(None))
} else {
generate_wit_name(name)
}
@ -254,7 +264,8 @@ impl WitType {
.join(", ")
),
WitType::Enum(variants) => format!(
"enum {{ {} }}",
"enum {} {{ {} }}",
name.unwrap_or_default(),
variants
.iter()
.map(|variant| generate_wit_name(variant))
@ -270,7 +281,7 @@ impl WitType {
.join(", ")
),
WitType::Handle(name) => format!("handle<{}>", generate_wit_name(name)),
WitType::TypeAlias(name, inner) => format!("type {} = {}", generate_wit_name(name), inner.to_wit()),
WitType::TypeAlias(name, inner) => format!("type {} = {}", generate_wit_name(name), inner.to_wit(None)),
WitType::FieldTy(name) => generate_wit_name(name)
}
}

@ -1,37 +1,48 @@
use std::collections::BTreeSet;
use oas3::spec::ParameterIn::Path;
use protox::prost_reflect::prost_types::{field_descriptor_proto, FileDescriptorProto, FileDescriptorSet};
use std::collections::{BTreeMap, BTreeSet};
use protox::prost_reflect::prost_types::{EnumDescriptorProto, FileDescriptorProto, FileDescriptorSet};
use tailcall_valid::{Valid, Validator};
use crate::config::config::{Config, Field, Interface, Record};
use crate::config::config::{Config, Interface, Record};
use crate::config::wit_types::WitType;
fn append_enums(config: &Config, file: &FileDescriptorProto) -> Valid<Record, anyhow::Error, anyhow::Error> {
todo!()
fn append_enums(_: &Config, file: &[EnumDescriptorProto]) -> Valid<BTreeMap<String, WitType>, anyhow::Error, anyhow::Error> {
Valid::from_iter(file.iter().enumerate(), |(i, enum_)| {
let enum_name = enum_.name();
Valid::from_iter(enum_.value.iter().enumerate(), |(j, value)| {
Valid::succeed(value.name().to_string())
}).and_then(|varients| {
Valid::succeed((enum_name.to_string(), WitType::Enum(varients)))
})
}).and_then(|rec| Valid::succeed(rec.into_iter().collect()))
}
fn append_message(config: &Config, file: &FileDescriptorProto) -> Valid<Record, anyhow::Error, anyhow::Error> {
todo!()
fn append_message(config: &Config, file: &FileDescriptorProto) -> Valid<Vec<Record>, anyhow::Error, anyhow::Error> {
Valid::succeed(vec![])
}
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| {
let mut map = BTreeMap::new();
let mut records = BTreeSet::new();
Valid::from_iter(set.file.iter(), |file| {
append_enums(&config, file).and_then(|rec| {
append_enums(&config, &file.enum_type).and_then(|varients| {
append_message(&config, file)
.and_then(|mut new_rec| {
new_rec.fields.extend(rec.fields);
Valid::succeed(new_rec)
.and_then(|recs| {
map.extend(varients);
records.extend(BTreeSet::from_iter(recs.into_iter()));
Valid::succeed(())
})
})
})
.and_then(|v| {
.and_then(|_| {
Valid::succeed(Interface {
name: "type".to_string(),
records: v.into_iter().collect(),
uses: vec![],
functions: vec![],
varients: map,
records,
..Default::default()
})
})
})

@ -11,6 +11,26 @@ impl Proto {
}
pub fn to_config(&self) -> Valid<Config, anyhow::Error, anyhow::Error> {
Valid::succeed(Config::default())
.and_then(|config| handle_types(config, &self.0))
.and_then(|config| handle_types(config, &self.0, "api:todos@1.0.0".to_string()))
}
}
#[cfg(test)]
mod t {
use tailcall_valid::Validator;
use wit_parser::Resolve;
use crate::proto::proto::Proto;
#[test]
fn foo() {
let proto = protox::compile(["foo.proto"], [env!("CARGO_MANIFEST_DIR").to_string()]).unwrap();
let proto = Proto::new([proto]);
let config = proto.to_config().to_result().unwrap();
println!("{}", config.to_wit());
// print!("{:#?}", config);
let mut resolve = Resolve::new();
resolve.push_str("foox.wit", &config.to_wit()).expect("TODO: panic message`");
println!("{:#?}", resolve);
}
}