Skip to content

Commit 84e19f4

Browse files
authored
39 basic rust types (#52)
* Add support for rust * Add generic type reification * Add cyclic reference detection
1 parent 3ad1bb1 commit 84e19f4

117 files changed

Lines changed: 2603 additions & 775 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yaml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ jobs:
8989
- uses: actions/checkout@v4
9090
- uses: actions/setup-node@v4
9191
with:
92-
node-version: 20
92+
node-version: 22
9393
- uses: actions/download-artifact@v4
9494
with:
9595
name: generated-sources
@@ -102,6 +102,14 @@ jobs:
102102
npm i
103103
npm run test
104104
105+
- uses: actions-rust-lang/setup-rust-toolchain@v1
106+
with:
107+
profile: minimal
108+
toolchain: 1.83.0
109+
- name: Test Rust
110+
working-directory: client-test/rust
111+
run: cargo test
112+
105113
# clean-artifact:
106114
# needs: [ jdk_compatibility_test, client_test ]
107115
# runs-on: ubuntu-latest

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,6 @@ build/
3333
### VS Code ###
3434
.vscode/*
3535
!.vscode/settings.json
36+
37+
### MacOS ###
38+
.DS_Store

README.md

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
[![CI](https://github.com/cuzfrog/sharedtype/actions/workflows/ci.yaml/badge.svg)](https://github.com/cuzfrog/sharedtype/actions/workflows/ci.yaml)
2+
![Maven Central Version](https://img.shields.io/maven-central/v/online.sharedtype/sharedtype?style=plastic)
3+
24
# SharedType - Sharing Java Types made easy
35
From Java:
46
```java
@@ -21,34 +23,32 @@ type User struct {
2123
Email string
2224
}
2325
```
24-
Rust (Planed):
26+
Rust:
2527
```rust
26-
struct User {
28+
pub struct User {
2729
name: String,
2830
age: i32,
2931
email: String,
3032
}
3133
```
32-
And more.
3334

3435
## Features
35-
* Java8 support. No hassles.
36+
* Java8 support.
3637
* Generics support.
3738
* (Planed) Constant support.
38-
* Client source dependency is only `@SharedType`. Nothing gets into bytecode/runtime.
39-
* SharedType AP jars <100KB, only 2 small dependencies: jsr305 annotations and [mustache](https://github.com/spullara/mustache.java). Download less.
40-
* Parsing takes milliseconds with `-proc:only`. Implemented with performance in head.
41-
* Intuitive defaults, put `@SharedType` and there you go.
42-
* Global + class level options. Fine tune your configs.
43-
44-
## Similar Projects
45-
* [bsorrentino/java2typescript](https://github.com/bsorrentino/java2typescript)
46-
* [vojtechhabarta/typescript-generator](https://github.com/vojtechhabarta/typescript-generator)
39+
* Client source dependency is only `@SharedType` retained at source code level.
40+
* SharedType AP jar <150KB, only 2 small dependencies: jsr305 annotations and [mustache](https://github.com/spullara/mustache.java).
41+
* Parsing takes milliseconds with `-proc:only`.
42+
* Intuitive defaults, put `@SharedType` and there you go. Global + class level options.
4743

4844
## Documentation
4945
* [User Guide](doc/Usage.md)
5046
* [Developer Guide](doc/Development.md)
5147

48+
## Similar Projects
49+
* [bsorrentino/java2typescript](https://github.com/bsorrentino/java2typescript)
50+
* [vojtechhabarta/typescript-generator](https://github.com/vojtechhabarta/typescript-generator)
51+
5252
## Authors
5353
Cause Chung (cuzfrog@gmail.com)
5454

annotation/src/main/java/online/sharedtype/SharedType.java

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,19 +30,52 @@
3030
* </p>
3131
*
3232
* <p>
33-
* <b>Inner class:</b><br>
33+
* <b>Inheritance:</b>
34+
* In different target schemas, inheritance may be transferred differently.
35+
* <ul>
36+
* <li>Typescript: Inheritance is mimicked. A subtype's inherited properties will not be included in its own declared properties,
37+
* while the supertype is also emitted. </li>
38+
* <li>Rust: Inheritance is not supported.
39+
* Type hierarchy will be flattened that a subtype's inherited properties will be included in its own declared properties,
40+
* while, by default, any supertypes will not be emitted again.</li>
41+
* </ul>
42+
* </p>
43+
*
44+
* <p>
45+
* <b>Inner classes:</b><br>
3446
* Declared inner and nested types will not be included by default, unless they are referenced by other types.
3547
* Non-static inner classes are not supported.
3648
* </p>
3749
*
3850
* <p>
51+
* <b>Cyclic Reference:</b><br>
52+
* <ul>
53+
* <li>Rust: Cyclic references will be wrapped in {@code Option<Box<T>>}.</li>
54+
* </ul>
55+
* </p>
56+
*
57+
* <p>
58+
* <b>Constants:</b><br>
59+
* Support is planned in upcoming versions. Only compile-time resolvable values or their combinations are supported.
60+
* </p>
61+
*
62+
* <p>
3963
* <b>Generics:</b><br>
40-
* Generics are supported. But it's also limited to target schema's capacity.
64+
* Generics are supported. But it's also limited to target schema's capacity. Currently, type bounds are not supported.
4165
* </p>
4266
*
4367
* <p>
4468
* <b>Collections:</b><br>
45-
* Iterables and arrays are treated as arrays. Map is mapped to:
69+
* Iterables and arrays are treated as arrays and, by default, are mapped to:
70+
* <ul>
71+
* <li>Typescript: {@code T[]}</li>
72+
* <li>Rust: {@code Vec<T>}</li>
73+
* </ul>
74+
*
75+
* Maps are mapped to:
76+
* <p>
77+
* <b>Maps:</b><br>
78+
* (Not supported yet.)
4679
* <ul>
4780
* <li>Typescript: {@code [key: string]: T} where {@code T} can be a reified type.</li>
4881
* </ul>
@@ -52,6 +85,7 @@
5285
* @author Cause Chung
5386
* @implNote generics type bounds are not supported yet, Map is not supported yet.
5487
*/
88+
// TODO: test user-defined array-like types
5589
@Retention(RetentionPolicy.SOURCE)
5690
@Target({java.lang.annotation.ElementType.TYPE})
5791
@Documented
@@ -86,6 +120,15 @@
86120
*/
87121
ComponentType[] includes() default {ComponentType.FIELDS, ComponentType.ACCESSORS, ComponentType.CONSTANTS};
88122

123+
/**
124+
* Macros to be added to the type in generated Rust code. E.g. "Debug" will generate {@code #[derive](Debug)}.
125+
* This property only affects this annotated type. By default, "Debug" and "PartialEq" are added to all types, which can be configured via global properties.
126+
* Resulted macros contain both global default and this property.
127+
*
128+
* @return Rust macro traits. E.g. "serde::Serialize".
129+
*/
130+
String[] rustMacroTraits() default {};
131+
89132
/**
90133
* Mark a method as an accessor regardless of its name.
91134
* Getter prefixes are configured in global properties.
@@ -100,7 +143,7 @@
100143
* Exclude fields, record components, accessors in a type, or a dependency type, e.g. a supertype.
101144
* <p>
102145
* <b>When placed on a type:</b> a subtype of this type will not extend this type in target code.
103-
* But if this type is referenced directly as type of a field or return type of an accessor, a compilation error will be reported,
146+
* But if this type is referenced directly as type of field or return type of accessor, a compilation error will be reported,
104147
* unless the field or accessor is also ignored.
105148
* </p>
106149
*/

client-test/rust/Cargo.lock

Lines changed: 96 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

client-test/rust/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
[package]
2+
name = "sharedtype-client-test-rust"
3+
version = "0.0.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
serde = { version = "1.0", features = ["derive"] }
8+
serde_json = "1.0"

client-test/rust/src/lib.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
mod types;
2+
3+
#[cfg(test)]
4+
mod tests {
5+
use super::types::*;
6+
7+
#[test]
8+
fn cyclic_dependencies() {
9+
let dep_a = DependencyClassA {
10+
b: Some(Box::new(DependencyClassB {
11+
c: Some(Box::new(DependencyClassC {
12+
a: Some(Box::new(DependencyClassA {
13+
b: None,
14+
a: 6,
15+
value: 33,
16+
notIgnoredImplementedMethod: 999,
17+
})),
18+
})),
19+
})),
20+
a: 5,
21+
value: 4,
22+
notIgnoredImplementedMethod: 5,
23+
};
24+
let json = serde_json::to_string(&dep_a).unwrap();
25+
26+
let dep_a_deser: DependencyClassA = serde_json::from_str(&json).unwrap();
27+
assert_eq!(dep_a_deser, dep_a);
28+
29+
print!("{}", &json);
30+
assert_eq!(&json, r#"{"b":{"c":{"a":{"b":null,"a":6,"value":33,"notIgnoredImplementedMethod":999}}},"a":5,"value":4,"notIgnoredImplementedMethod":5}"#);
31+
}
32+
33+
#[test]
34+
fn recursieve_type() {
35+
let recusive_class = RecursiveClass {
36+
directRef: Some(Box::new(RecursiveClass {
37+
directRef: None,
38+
arrayRef: vec![],
39+
})),
40+
arrayRef: vec![Box::new(RecursiveClass {
41+
directRef: None,
42+
arrayRef: vec![],
43+
})],
44+
};
45+
46+
let json = serde_json::to_string(&recusive_class).unwrap();
47+
48+
let recusive_class_deser: RecursiveClass = serde_json::from_str(&json).unwrap();
49+
assert_eq!(recusive_class_deser, recusive_class);
50+
51+
print!("{}", &json);
52+
assert_eq!(&json, r#"{"directRef":{"directRef":null,"arrayRef":[]},"arrayRef":[{"directRef":null,"arrayRef":[]}]}"#);
53+
}
54+
}

client-test/rust/src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../../it/java17/target/generated-sources/types.rs

client-test/typescript/setenv

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
22

3-
export PATH=$NODE20_HOME/bin:./node_modules/.bin:$PATH
3+
export PATH=$NODE22_HOME/bin:./node_modules/.bin:$PATH
44
echo Node:"$(node -v)"
55

client-test/typescript/tests/types.java17.test.ts

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {DependencyClassA, DependencyClassB, DependencyClassC, EnumGalaxy, EnumSize, EnumTShirt, JavaRecord, AnotherJavaClass} from "../src/index.java17.js";
1+
import type { DependencyClassA, DependencyClassB, DependencyClassC, EnumGalaxy, EnumSize, EnumTShirt, JavaRecord, AnotherJavaClass, RecursiveClass } from "../src/index.java17.js";
22

33
export const list1: EnumGalaxy[] = ["Andromeda", "MilkyWay", "Triangulum"];
44
export const record1: Record<EnumTShirt, number> = {
@@ -8,7 +8,9 @@ export const record1: Record<EnumTShirt, number> = {
88
}
99
export const size1: EnumSize = 1;
1010

11-
export const dependencyClassC: DependencyClassC = {} as DependencyClassC;
11+
export const dependencyClassC: DependencyClassC = {
12+
a: {} as DependencyClassA, // TODO: optional for cyclic dependency
13+
};
1214

1315
export const dependencyClassB: DependencyClassB = {
1416
c: dependencyClassC
@@ -22,7 +24,7 @@ export const dependencyClassA: DependencyClassA = {
2224
};
2325
dependencyClassC.a = dependencyClassA
2426

25-
export const obj: Omit<JavaRecord<string, number>, "aVoid" | "genericMap"> = {
27+
export const obj: Omit<JavaRecord<string>, "aVoid" | "genericMap"> = {
2628
boxedBoolean: false,
2729
boxedByte: 0,
2830
boxedChar: "",
@@ -58,3 +60,11 @@ export const obj: Omit<JavaRecord<string, number>, "aVoid" | "genericMap"> = {
5860
export const anotherJavaClass: AnotherJavaClass = {
5961
value: 333,
6062
}
63+
64+
export const recursiveClass: RecursiveClass = {
65+
directRef: {
66+
directRef: {} as RecursiveClass, // TODO: optional for cyclic dependency
67+
arrayRef: [],
68+
},
69+
arrayRef: [],
70+
}

0 commit comments

Comments
 (0)