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

[Feature Request] Improve TypeScript generator #43

Open
MrFoxPro opened this issue Sep 10, 2024 · 2 comments · May be fixed by #46
Open

[Feature Request] Improve TypeScript generator #43

MrFoxPro opened this issue Sep 10, 2024 · 2 comments · May be fixed by #46
Labels
enhancement New feature or request

Comments

@MrFoxPro
Copy link

I believe output like with ts-proto when it's possible to encode plain objects would be much beter then using classes:

message ImageEditDescriptor {
	oneof type {
		bytes replacement = 1;
		string key = 2;
	}
}

output ts:

export interface ImageEditDescriptor {
  type?: { $case: "replacement"; replacement: Uint8Array } | { $case: "key"; key: string } | undefined;
}
export const ImageEditDescriptor = {
  encode(message: ImageEditDescriptor, writer: _m0.Writer = _m0.Writer.create()): _m0.Writer {
    switch (message.type?.$case) {
      case "replacement":
        writer.uint32(10).bytes(message.type.replacement);
        break;
      case "key":
        writer.uint32(18).string(message.type.key);
        break;
    }
    return writer;
  },

  decode(input: _m0.Reader | Uint8Array, length?: number): ImageEditDescriptor {
    const reader = input instanceof _m0.Reader ? input : _m0.Reader.create(input);
    let end = length === undefined ? reader.len : reader.pos + length;
    const message = createBaseImageEditDescriptor();
    while (reader.pos < end) {
      const tag = reader.uint32();
      switch (tag >>> 3) {
        case 1:
          if (tag !== 10) {
            break;
          }

          message.type = { $case: "replacement", replacement: reader.bytes() };
          continue;
        case 2:
          if (tag !== 18) {
            break;
          }

          message.type = { $case: "key", key: reader.string() };
          continue;
      }
      if ((tag & 7) === 4 || tag === 0) {
        break;
      }
      reader.skipType(tag & 7);
    }
    return message;
  },

  create<I extends Exact<DeepPartial<ImageEditDescriptor>, I>>(base?: I): ImageEditDescriptor {
    return ImageEditDescriptor.fromPartial(base ?? ({} as any));
  },
  fromPartial<I extends Exact<DeepPartial<ImageEditDescriptor>, I>>(object: I): ImageEditDescriptor {
    const message = createBaseImageEditDescriptor();
    if (
      object.type?.$case === "replacement" &&
      object.type?.replacement !== undefined &&
      object.type?.replacement !== null
    ) {
      message.type = { $case: "replacement", replacement: object.type.replacement };
    }
    if (object.type?.$case === "key" && object.type?.key !== undefined && object.type?.key !== null) {
      message.type = { $case: "key", key: object.type.key };
    }
    return message;
  },
};
@MrFoxPro MrFoxPro added the enhancement New feature or request label Sep 10, 2024
@MrFoxPro MrFoxPro linked a pull request Sep 13, 2024 that will close this issue
@ma2bd
Copy link
Contributor

ma2bd commented Sep 14, 2024

In which way is it better? Performance?

@MrFoxPro
Copy link
Author

MrFoxPro commented Sep 14, 2024

In which way is it better? Performance?

Maybe a little, but main point is it's way more convinient to use. Let's say we want to encode ComplexStruct

struct SimpleStruct {
	a: u32,
	b: String,
}
enum MultiEnum {
	VariantA(i32),
	VariantB(String),
	VariantC { x: u8, y: f64 },
	UnitVariant, // Unit variant added
}
struct UnitStruct;
struct NewtypeStruct(i32);
struct TupleStruct(i32, f64, String);
struct ComplexStruct {
	flag: bool,
	inner: SimpleStruct,
	items: Vec<MultiEnum>,
	unit: UnitStruct,
	newtype: NewtypeStruct,
	tuple: TupleStruct,
	map: HashMap<i32, i64>
}

from Rust to TypeScript.
With #46, we can do it like this:

import * as Registry from "./bincode/registry.ts" // generated file
const ComplexStruct_obj: Registry.ComplexStruct = { // using it as Type
	inner: { a: 42, b: "Hello" },
	flag: true,
	items: [
		{ $: "VariantA", VariantA: 10 },
		{ $: "VariantB", VariantB: "World" }
	],
	unit: null,
	newtype: 99,
	tuple: [123, 45.67, "Test"],
	map: new Map().set(3, 7n)
}
const encoded = Registry.ComplexStruct.encode(ComplexStruct_obj) // using object CompexStruct

We can also in some code use only type imports:
import { type ComplexStruct } from "./bincode/registry.ts"

This is way more convinient than writing new ComplexStruct(..., new MultiEnumVariantC(... new X(..., new Y(), ...)), ...) and so on.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants