diff --git a/foo.proto b/foo.proto index ff2852c..f856ff3 100644 --- a/foo.proto +++ b/foo.proto @@ -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; diff --git a/src/config/config.rs b/src/config/config.rs index 84761df..0e73873 100644 --- a/src/config/config.rs +++ b/src/config/config.rs @@ -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, pub records: BTreeSet, pub uses: Vec, pub functions: Vec, diff --git a/src/config/to_wit.rs b/src/config/to_wit.rs index 80d87aa..d010ffb 100644 --- a/src/config/to_wit.rs +++ b/src/config/to_wit.rs @@ -105,6 +105,13 @@ impl Interface { .collect::>() .join("\n "); + let varients = self + .varients + .iter() + .map(|(name, ty)| format!("{}", ty.to_wit(Some(generate_wit_name(name))))) + .collect::>() + .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 { 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::>().join(", ") + elements.iter().map(|e| e.to_wit(None)).collect::>().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::>() .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) } } diff --git a/src/proto/handle_types.rs b/src/proto/handle_types.rs index 1dfae4a..1a3ddc1 100644 --- a/src/proto/handle_types.rs +++ b/src/proto/handle_types.rs @@ -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 { - todo!() +fn append_enums(_: &Config, file: &[EnumDescriptorProto]) -> Valid, 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 { - todo!() +fn append_message(config: &Config, file: &FileDescriptorProto) -> Valid, anyhow::Error, anyhow::Error> { + Valid::succeed(vec![]) } pub fn handle_types(config: Config, proto: &[FileDescriptorSet], package: String) -> Valid { 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() }) }) }) diff --git a/src/proto/proto.rs b/src/proto/proto.rs index 5227a1b..d513e6f 100644 --- a/src/proto/proto.rs +++ b/src/proto/proto.rs @@ -11,6 +11,26 @@ impl Proto { } pub fn to_config(&self) -> Valid { 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); } } \ No newline at end of file