Skip to content

Commit

Permalink
Fix/aflowt shutdown (#75)
Browse files Browse the repository at this point in the history
* add union support (requires protocol=2); fix f32 and f64 encoder/decoder

Signed-off-by: Steve <[email protected]>

* update nats-aflowt to 0.16.104; update crate to 0.7.2

Signed-off-by: Steve <[email protected]>

* add Cargo.toml back

Signed-off-by: Steve <[email protected]>

* fix deprecation messages

Signed-off-by: Steve <[email protected]>
  • Loading branch information
stevelr authored Feb 7, 2022
1 parent 934f3f9 commit ccfde57
Show file tree
Hide file tree
Showing 11 changed files with 432 additions and 71 deletions.
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[workspace]
members = [ "codegen", "rpc-rs" ]
2 changes: 1 addition & 1 deletion codegen/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "weld-codegen"
version = "0.3.0"
version = "0.3.1"
edition = "2021"
authors = [ "wasmcloud Team" ]
license = "Apache-2.0"
Expand Down
65 changes: 59 additions & 6 deletions codegen/src/codegen_rust.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,20 @@ enum MethodArgFlags {
ToString,
}

/// Returns true if the type is a rust primitive
pub fn is_rust_primitive(id: &ShapeID) -> bool {
(id.namespace() == prelude_namespace_id()
&& matches!(
id.shape_name().to_string().as_str(),
"Boolean" | "Byte" | "Short" | "Integer" | "Long" | "Float" | "Double"
))
|| (id.namespace() == wasmcloud_model_namespace()
&& matches!(
id.shape_name().to_string().as_str(),
"U64" | "U32" | "U16" | "U8" | "I64" | "I32" | "I16" | "I8" | "F64" | "F32"
))
}

impl<'model> CodeGen for RustCodeGen<'model> {
fn output_language(&self) -> OutputLanguage {
OutputLanguage::Rust
Expand Down Expand Up @@ -185,7 +199,6 @@ impl<'model> CodeGen for RustCodeGen<'model> {
Some(ns) => Some(NamespaceID::from_str(ns)?),
None => None,
};
//self.protocol = model.wasmbus_
if let Some(ref ns) = self.namespace {
if self.packages.get(&ns.to_string()).is_none() {
print_warning(&format!(
Expand Down Expand Up @@ -302,10 +315,12 @@ impl<'model> CodeGen for RustCodeGen<'model> {
ShapeKind::Structure(strukt) => {
self.declare_structure_shape(w, id.shape_name(), traits, strukt)?;
}
ShapeKind::Union(strukt) => {
self.declare_union_shape(w, id.shape_name(), traits, strukt)?;
}
ShapeKind::Operation(_)
| ShapeKind::Resource(_)
| ShapeKind::Service(_)
| ShapeKind::Union(_)
| ShapeKind::Unresolved => {}
}

Expand Down Expand Up @@ -473,6 +488,8 @@ impl<'model> RustCodeGen<'model> {
s.push('i');
s.push_str(&name[1..]);
}
"F64" => s.push_str("f64"),
"F32" => s.push_str("f32"),
_ => {
if self.namespace.is_none()
|| self.namespace.as_ref().unwrap() != id.namespace()
Expand Down Expand Up @@ -721,6 +738,40 @@ impl<'model> RustCodeGen<'model> {
Ok(())
}

fn declare_union_shape(
&mut self,
w: &mut Writer,
id: &Identifier,
traits: &AppliedTraits,
strukt: &StructureOrUnion,
) -> Result<()> {
let (fields, is_numbered) = get_sorted_fields(id, strukt)?;
if !is_numbered {
return Err(Error::Model(format!(
"union {} must have numbered fields",
id
)));
}
self.apply_documentation_traits(w, id, traits);
w.write(b"#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]\n");
println!("Union: {}:\n:{:#?}", id, strukt);

w.write(b"pub enum ");
self.write_ident(w, id);
w.write(b" {\n");
for member in fields.iter() {
self.apply_documentation_traits(w, member.id(), member.traits());
let variant_name = self.to_type_name(&member.id().to_string());
w.write(&format!(
"{}({}),\n",
variant_name,
self.type_string(Ty::Shape(member.target()))?
)); // TODO: Ty::Ref ?
}
w.write(b"}\n\n");
Ok(())
}

/// Declares the service as a rust Trait whose methods are the smithy service operations
fn write_service_interface(
&mut self,
Expand Down Expand Up @@ -850,6 +901,7 @@ impl<'model> RustCodeGen<'model> {
w.write(b" : MessageDispatch + ");
self.write_ident(w, service.id);
let proto = crate::model::wasmbus_proto(service.traits)?;
let has_cbor = proto.map(|pv| pv.has_cbor()).unwrap_or(false);
w.write(
br#"{
async fn dispatch(
Expand All @@ -875,7 +927,7 @@ impl<'model> RustCodeGen<'model> {
if let Some(op_input) = op.input() {
let symbol = op_input.shape_name().to_string();
// let value : InputType = deserialize(...)?;
if proto.has_cbor() {
if has_cbor {
w.write(&format!(
r#"
let value : {} = {}::common::decode(&message.arg, &decode_{})
Expand Down Expand Up @@ -916,7 +968,7 @@ impl<'model> RustCodeGen<'model> {

if let Some(_op_output) = op.output() {
// serialize result
if proto.has_cbor() {
if has_cbor {
w.write(&format!(
"let mut e = {}::cbor::vec_encoder();\n",
&self.import_core
Expand Down Expand Up @@ -965,6 +1017,7 @@ impl<'model> RustCodeGen<'model> {
self.write_comment(w, CommentKind::Documentation, &doc);
self.apply_documentation_traits(w, service.id, service.traits);
let proto = crate::model::wasmbus_proto(service.traits)?;
let has_cbor = proto.map(|pv| pv.has_cbor()).unwrap_or(false);
w.write(&format!(
r#"/// client for sending {} messages
#[derive(Debug)]
Expand Down Expand Up @@ -1010,7 +1063,7 @@ impl<'model> RustCodeGen<'model> {
let _arg_is_string = matches!(arg_flags, MethodArgFlags::ToString);
w.write(b" {\n");
if let Some(_op_input) = op.input() {
if proto.has_cbor() {
if has_cbor {
if _arg_is_string {
w.write(b"let arg = arg.to_string();\n");
}
Expand Down Expand Up @@ -1053,7 +1106,7 @@ impl<'model> RustCodeGen<'model> {
w.write(b"\", arg: Cow::Borrowed(&buf)}, None).await?;\n");
if let Some(op_output) = op.output() {
let symbol = op_output.shape_name().to_string();
if proto.has_cbor() {
if has_cbor {
w.write(&format!(
r#"
let value : {} = {}::common::decode(&resp, &decode_{})
Expand Down
70 changes: 39 additions & 31 deletions codegen/src/decode_rust.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
//! CBOR Decode functions
use crate::{
codegen_rust::{is_optional_type, RustCodeGen},
codegen_rust::{is_optional_type, is_rust_primitive, RustCodeGen},
error::{Error, Result},
gen::CodeGen,
model::{wasmcloud_model_namespace, Ty},
Expand Down Expand Up @@ -110,6 +110,8 @@ impl<'model> RustCodeGen<'model> {
b"I32" => decode_integer().to_string(),
b"I16" => decode_short().to_string(),
b"I8" => decode_byte().to_string(),
b"F64" => decode_double().to_string(),
b"F32" => decode_float().to_string(),
_ => {
let mut s = String::new();
if self.namespace.is_none()
Expand Down Expand Up @@ -160,7 +162,6 @@ impl<'model> RustCodeGen<'model> {
Ok(stmt)
}

#[allow(dead_code)]
fn decode_shape_kind(&self, id: &ShapeID, kind: &ShapeKind) -> Result<String> {
let s = match kind {
ShapeKind::Simple(simple) => match simple {
Expand Down Expand Up @@ -230,21 +231,50 @@ impl<'model> RustCodeGen<'model> {
)
}
ShapeKind::Structure(strukt) => self.decode_struct(id, strukt)?,
ShapeKind::Union(union_) => self.decode_union(id, union_)?,
ShapeKind::Operation(_)
| ShapeKind::Resource(_)
| ShapeKind::Service(_)
| ShapeKind::Unresolved => String::new(),

ShapeKind::Union(_) => {
unimplemented!();
}
};
Ok(s)
}

fn decode_union(&self, id: &ShapeID, strukt: &StructureOrUnion) -> Result<String> {
let (fields, _) = crate::model::get_sorted_fields(id.shape_name(), strukt)?;
let enum_name = id.shape_name();
let mut s = format!(
r#"
// decoding union {}
let len = d.array()?.ok_or_else(||RpcError::Deser("decoding union '{}': indefinite array not supported".to_string()))?;
if len != 2 {{ return Err(RpcError::Deser("decoding union '{}': expected 2-array".to_string())); }}
match d.u16()? {{
"#,
enum_name, enum_name, enum_name
);
for field in fields.iter() {
let field_num = field.field_num().unwrap();
let field_name = self.to_type_name(&field.id().to_string());
let field_decoder = self.decode_shape_id(field.target())?;
s.push_str(&format!(
r#"
{} => {{
let val = {};
{}::{}(val)
}},
"#,
&field_num, field_decoder, enum_name, field_name
));
}
s.push_str(&format!(r#"
n => {{ return Err(RpcError::Deser(format!("invalid field number for union '{}':{{}}", n))); }},
}}
"#, id));
Ok(s)
}

/// write decode statements for a structure
/// This always occurs inside a dedicated function for the struct type
#[allow(dead_code)]
fn decode_struct(&self, id: &ShapeID, strukt: &StructureOrUnion) -> Result<String> {
let (fields, _is_numbered) = crate::model::get_sorted_fields(id.shape_name(), strukt)?;
let mut s = String::new();
Expand Down Expand Up @@ -419,7 +449,6 @@ impl<'model> RustCodeGen<'model> {
/// name of the function is encode_<S> where <S> is the camel_case type name
/// It is generated in the module that declared type S, so it can always
/// be found by prefixing the function name with the module path.
#[allow(dead_code)]
pub(crate) fn declare_shape_decoder(
&self,
w: &mut Writer,
Expand All @@ -429,12 +458,12 @@ impl<'model> RustCodeGen<'model> {
match kind {
ShapeKind::Simple(_)
| ShapeKind::Structure(_)
| ShapeKind::Union(_)
| ShapeKind::Map(_)
| ShapeKind::List(_)
| ShapeKind::Set(_) => {
let name = id.shape_name();
let is_rust_copy = vec!["U8", "I8", "U16", "I16", "U32", "I32", "U64", "I64"]
.contains(&name.to_string().as_str());
let is_rust_copy = is_rust_primitive(id);
let mut s = format!(
r#"
// Decode {} from cbor input stream
Expand All @@ -452,31 +481,10 @@ impl<'model> RustCodeGen<'model> {
s.push_str(&body);
s.push_str("};\n Ok(__result)\n}\n");
w.write(s.as_bytes());

/***
if !is_rust_copy {
let cbor_decode_impl = format!(
r#"
impl {}::common::Decode for {} {{
fn decode(d: &mut {}::cbor::Decoder) -> Result<{}, RpcError> {{
decode_{}(d)
}}
}}
"#,
self.import_core,
name,
self.import_core,
name,
crate::strings::to_snake_case(&name.to_string()),
);
w.write(&cbor_decode_impl);
}
***/
}
ShapeKind::Operation(_)
| ShapeKind::Resource(_)
| ShapeKind::Service(_)
| ShapeKind::Union(_)
| ShapeKind::Unresolved => { /* write nothing */ }
}
Ok(())
Expand Down
Loading

0 comments on commit ccfde57

Please sign in to comment.