Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native Type Generation Support #7

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
169 changes: 169 additions & 0 deletions src/codegen/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use case::CaseExt;
use std::io;

use core::mem::size_of;
use std::io::Write;

// Little Endian
pub type Number = u32;
Expand Down Expand Up @@ -59,6 +60,18 @@ func {struct_name}Default() {struct_name} {{
writeln!(writer, "{}", default)?;
Ok(())
}

// mark this as false to keep the original behavior
fn need_unpack() -> bool { false }
}

/// For generate native conversion codes
pub trait NativeGenerator : HasName {

/// Whether this type needs to unpack
fn need_unpack() -> bool;

fn native_type_support_generate(&self, writer: &mut impl io::Write) -> io::Result<()>;
}

impl Generator for ast::Option_ {
Expand Down Expand Up @@ -118,6 +131,23 @@ func (s *{struct_name}) AsBuilder() {struct_name}Builder {{
}
}

impl NativeGenerator for ast::Option_ {
fn need_unpack() -> bool {
true
}

fn native_type_support_generate(&self, writer: &mut impl io::Write) -> io::Result<()> {
Ok(())
}
}

//impl Generator for ast::Primitive {
// fn generate<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
// self.native_type_support_generate(writer)?;
// Ok(())
// }
//}

impl Generator for ast::Union {
fn generate<W: io::Write>(&self, writer: &mut W) -> io::Result<()> {
writeln!(writer, "{}", self.gen_builder())?;
Expand Down Expand Up @@ -163,6 +193,25 @@ func (s *{struct_name}) AsBuilder() {struct_name}Builder {{
struct_name = struct_name
);
writeln!(writer, "{}", struct_impl)?;
self.native_type_support_generate(writer)?;
Ok(())
}
}

impl NativeGenerator for ast::Union {
fn need_unpack() -> bool {
true
}

fn native_type_support_generate(&self, writer: &mut impl io::Write) -> io::Result<()> {
let struct_name = self.name().to_camel();
let def = format!(
r#"
func Unpack{struct_name}(v *{struct_name}) *{struct_name}Union {{
return v.ToUnion()
}}
"#);
writeln!(writer, "{}", def)?;
Ok(())
}
}
Expand Down Expand Up @@ -305,6 +354,79 @@ func (s *{struct_name}) {func_name}() *{inner} {{
let as_builder = impl_as_builder_for_struct_or_table(&struct_name, self.fields());
writeln!(writer, "{}", as_builder)?;

self.native_type_support_generate(writer)?;
Ok(())
}
}

impl NativeGenerator for ast::Primitive {
fn need_unpack() -> bool {
true
}

fn native_type_support_generate(&self, writer: &mut impl Write) -> io::Result<()> {
let struct_name = self.name().to_camel();
let (unpack_def, native_type_name) = match self.size() {
1 => ("return binary.LittleEndian.Uint8(v.inner)", "uint8"),
2 => ("return binary.LittleEndian.Uint16(v.inner)", "uint16"),
4 => ("return binary.LittleEndian.Uint32(v.inner)", "uint32"),
8 => ("return binary.LittleEndian.Uint64(v.inner)", "uint64"),
_ => unreachable!("invalid size"),
};

writeln!(writer,"{}", format!(r#"
func Unpack{struct_name}(v *{struct_name}) {native_type_name} {{
{unpack_def}
}}
"#))?;
Ok(())
}
}

impl NativeGenerator for ast::Struct {
fn need_unpack() -> bool {
true
}

fn native_type_support_generate(&self, writer: &mut impl Write) -> io::Result<()> {
let struct_name = self.name().to_camel();
let struct_fields_def = self.fields().iter().map(|f| {
let field_name = f.name().to_camel();
let field_type = f.typ().name().to_camel();
format!("{} *{} `json:\"{}\"`", field_name, field_type, f.name())
}).collect::<Vec<String>>().join("\n");

// Generates the struct definition
let struct_def = format!(r#"
type Native{struct_name} struct {{
{struct_fields_def}
}}
"#);
writeln!(writer, "{}", struct_def)?;

let fields_unpack_def = self.fields().iter().map(|f| {

let field_name = f.name().to_camel();
let field_type = f.typ().name().to_camel();
if f.typ().is_byte() {
format!("native_val.{} = v.{}()", field_name, field_name)
} else {
format!("native_val.{} = Unpack{}(v.{}())", field_name, field_type, field_name)
}
}).collect::<Vec<String>>().join("\n");

// Generates Unpacking function
let unpack_def = format!(r#"
func Unpack{struct_name}(v *{struct_name}) *Native{struct_name} {{
native_val := &Native{struct_name}{{
}}
//s := v.AsBuilder()
{fields_unpack_def}
return native_val
}}
"#);
writeln!(writer, "{}", unpack_def)?;

Ok(())
}
}
Expand Down Expand Up @@ -742,3 +864,50 @@ func (s *{struct_name}) {func}() *{inner} {{
Ok(())
}
}

impl NativeGenerator for ast::Table {
fn need_unpack() -> bool {
true
}

fn native_type_support_generate(&self, writer: &mut impl Write) -> io::Result<()> {
let struct_name = self.name().to_camel();
let struct_fields_def = self.fields().iter().map(|f| {
let field_name = f.name().to_camel();
let field_type = f.typ().name().to_camel();
format!("{} *{} `json:\"{}\"`", field_name, field_type, f.name())
}).collect::<Vec<String>>().join("\n");

// Generates the struct definition
let struct_def = format!(r#"
type Native{struct_name} struct {{
{struct_fields_def}
}}
"#);
writeln!(writer, "{}", struct_def)?;

let fields_unpack_def = self.fields().iter().map(|f| {
let field_name = f.name().to_camel();
let field_type = f.typ().name().to_camel();
if f.typ().is_byte() {
format!("native_val.{} = s.{}()", field_name, field_name)
} else {
format!("native_val.{} = Unpack{}(s.{}())", field_name, field_type, field_name)
}
}).collect::<Vec<String>>().join("\n");

// Generates Unpacking function
let unpack_def = format!(r#"
func Unpack{struct_name}(v *{struct_name}) *Native{struct_name} {{
native_val := &Native{struct_name}{{
}}
s := v.AsBuilder()
{fields_unpack_def}
return native_val
}}
"#);
writeln!(writer, "{}", unpack_def)?;

Ok(())
}
}
4 changes: 4 additions & 0 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ func packNumber(num Number) []byte {
binary.LittleEndian.PutUint32(b, uint32(num))
return b
}

func UnpackByte(b Byte) byte {
return b.inner
}
"#,
);

Expand Down