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

feat: implement RustGenerator proof-of-concept #818

Merged
merged 20 commits into from
Aug 6, 2022

Conversation

leigh-johnson
Copy link
Collaborator

@leigh-johnson leigh-johnson commented Jul 26, 2022

Description

Implements RustGenerator proof of concept with support for basic primitives, enum, structs, tuple, and union types.

Usage example

Check out examples/rust-generate-crate for a demo. You'll need to install Rust to compile the generated package.

Feature table

Feature Status Info
Union (polymorphic type) ✅ done
Enum (group of constants) ✅ done
Array (unordered collection) ✅ done
Tuple (ordered collection) ✅ done

Next steps

  • Implement To/From String methods (serde_json)
  • Implement To/From u8 bytes methods (serde_bytes)
  • Publish asyncapi-nats-rs repo for a full example of models in the wild

Related issue(s)
Fixes #509

Copy link
Contributor

@github-actions github-actions bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Welcome to AsyncAPI. Thanks a lot for creating your first pull request. Please check out our contributors guide useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.

@leigh-johnson leigh-johnson changed the title Implement RustGenerator proof-of-concept feat: Implement RustGenerator proof-of-concept Jul 26, 2022
@leigh-johnson leigh-johnson changed the title feat: Implement RustGenerator proof-of-concept feat: implement RustGenerator proof-of-concept Jul 26, 2022
Copy link
Member

@jonaslagoni jonaslagoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, that was damn quick and you even targeted next 🤩💪 Had a few comments and suggestions but overall looks great!

You can ignore all the CI checks, I am trying to solve them in another PR, so we merge regardless of failures.

Some extra changes which are needed:

If you want to continue to be engaged and take ownership of the rust generator feel free to add yourself as code owner in this PR 👍

docs/languages/Rust.md Outdated Show resolved Hide resolved
docs/languages/Rust.md Outdated Show resolved Hide resolved
docs/languages/Rust.md Outdated Show resolved Hide resolved
examples/rust-generate-crate/index.ts Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Outdated Show resolved Hide resolved
src/generators/rust/renderers/TupleRenderer.ts Outdated Show resolved Hide resolved
src/generators/rust/renderers/UnionRenderer.ts Outdated Show resolved Hide resolved
examples/rust-generate-crate/index.ts Outdated Show resolved Hide resolved
@leigh-johnson
Copy link
Collaborator Author

Thank you for the thorough & thoughtful review! I blocked some time to check in revisions tomorrow (Friday) AM PDT.

💎 I should mention that I originally worked from master - so I really appreciate how much effort went into improving the generator development experience for next. The MetaModel refactor was excellent and made it a breeze to jump right in. Nice job y'all!

Wow, that was damn quick and you even targeted next star_struckmuscle Had a few comments and suggestions but overall looks great!

You can ignore all the CI checks, I am trying to solve them in another PR, so we merge regardless of failures.

Some extra changes which are needed:

If you want to continue to be engaged and take ownership of the rust generator feel free to add yourself as code owner in this PR +1

@leigh-johnson
Copy link
Collaborator Author

How do y'all prefer to solve merge conflicts? Let me know if you prefer I rebase and force-push, create a merge commit from next -> branch, or merge next -> branch with --no-ff

Copy link
Member

@jonaslagoni jonaslagoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do y'all prefer to solve merge conflicts? Let me know if you prefer I rebase and force-push, create a merge commit from next -> branch, or merge next -> branch with --no-ff

That is entirely up to you, it's your branch so you can do whatever you prefer 🙂 We are squashing commits when we merge, so nothing will be visible from Modelina's perspective.

Only had one small change otherwise it looks good 👍 You also have 2 small code smells :)

README.md Show resolved Hide resolved
examples/rust-generate-crate/index.ts Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Show resolved Hide resolved
@leigh-johnson leigh-johnson force-pushed the issue-509-rust-generator-next branch from c01bdc6 to 1958a07 Compare August 2, 2022 16:03
@leigh-johnson
Copy link
Collaborator Author

Just rebased & fixed the last lingering code smells. Thanks again for helping me polish up this PR and for all your work on AsyncAPI. 🙇‍♀️

Stay tuned for a Rust + NATS client generator next.✌️

Copy link
Member

@jonaslagoni jonaslagoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You removed a newline in the generator, so the test snapshots needs to be updated 🙂 And then the Blackbox tests have some remaining merge conflicts.

Other then that it LGTM 🎉

Just rebased & fixed the last lingering code smells. Thanks again for helping me polish up this PR and for all your work on AsyncAPI.
Stay tuned for a Rust + NATS client generator next.

Thanks for taking the time to contribute! Cant wait 🎉

test/blackbox/blackbox.spec.ts Outdated Show resolved Hide resolved
@jonaslagoni
Copy link
Member

You can ignore the code smells, those seem to be mine 🧐

Regarding the bug, that seems like its relevant, or is it a false positive?

Copy link
Member

@jonaslagoni jonaslagoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I forgot to run the CI before last review 🧐 My bad, as it seems to have caught some things. Added some suggestions how to fix the linter.

Regarding the blackbox it's related to assuming originalInput has some value, which in some cases don't. Not sure on the specifics why it's the case here with JSON Schema inputs, have to debug the blackbox tests to figure that one out 🤔

Unless you have clear idea about a fix, I am good with merging and then create issue to fix later as we are still in pre-release.

src/generators/rust/renderers/EnumRenderer.ts Outdated Show resolved Hide resolved
src/generators/rust/renderers/EnumRenderer.ts Outdated Show resolved Hide resolved
src/generators/rust/presets/CommonPreset.ts Outdated Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Outdated Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Outdated Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Show resolved Hide resolved
src/generators/rust/renderers/EnumRenderer.ts Outdated Show resolved Hide resolved
Co-authored-by: Jonas Lagoni <jonas-lt@live.dk>
leigh-johnson and others added 2 commits August 6, 2022 10:44
Co-authored-by: Jonas Lagoni <jonas-lt@live.dk>
Co-authored-by: Jonas Lagoni <jonas-lt@live.dk>
@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 6, 2022

Please retry analysis of this Pull-Request directly on SonarCloud.

Copy link
Member

@jonaslagoni jonaslagoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be the last suggestions for linter.

The blackbox tests fails, but lets fix it at another time, might need to spend some time debugging to get to the bottom of the issue.

examples/rust-generate-crate/index.spec.ts Outdated Show resolved Hide resolved
src/generators/rust/RustFileGenerator.ts Outdated Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Outdated Show resolved Hide resolved
src/generators/rust/RustGenerator.ts Outdated Show resolved Hide resolved
@sonarqubecloud
Copy link

sonarqubecloud bot commented Aug 6, 2022

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 4 Code Smells

No Coverage information No Coverage information
0.0% 0.0% Duplication

Copy link
Member

@jonaslagoni jonaslagoni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

@jonaslagoni
Copy link
Member

/rtm

@asyncapi-bot asyncapi-bot merged commit 110b011 into asyncapi:next Aug 6, 2022
@jonaslagoni
Copy link
Member

@all-contributors please add @leigh-johnson for code, test, example, docs, maintenance

@allcontributors
Copy link
Contributor

@jonaslagoni

I've put up a pull request to add @leigh-johnson! 🎉

@asyncapi-bot
Copy link
Contributor

🎉 This PR is included in version 1.0.0-next.2 🎉

The release is available on:

Your semantic-release bot 📦🚀

@jonaslagoni
Copy link
Member

The team grows @magicmatatjahu @Samridhi-98 @ron-debajyoti 🎉

@leigh-johnson you should have been invited to join as collaborator 😃 Welcome to the team!

You are also illegible to join the AsyncAPI TSC (in case you didn't catch that 😄), all you have to do is add yourself to the list of TSC members here: https://github.com/asyncapi/community/blob/master/TSC_MEMBERS.json. An example of how to do it can be seen here: asyncapi/community#430

Glad to have you onboard, and thanks for the patience with this PR 🍺

@leigh-johnson leigh-johnson deleted the issue-509-rust-generator-next branch August 7, 2022 17:19
jonaslagoni added a commit that referenced this pull request Jan 23, 2023
## [1.0.0](v0.59.9...v1.0.0) (2023-01-23)

### Upgrade Steps

You can find the migration details here: https://github.com/asyncapi/modelina/blob/master/docs/migration.md 

Dont hesitate to reach out if you need help migrating to version 1.

### Breaking Changes
There is no specific PR that contains the breaking changes but is part of multiple PRs. See the migration part above.

### New Features
* feat: add Rust Generator (#818)
* feat: add Kotlin model generator (#1074)
* feat: add Python generator (#863)
* feat: add jsonbinpack preset for TypeScript (#854)
* feat: add support for AsyncAPI 2.5 (#893)
* feat: add support for oneOf and anyOf as UnionModel (#899)
* feat: integrate new AsyncAPI parser version (#925)
* feat: add C# Newtonsoft preset (#970)
* feat: add access to entire property object in constrainer (#985)
* feat: add precise csharp enum type (#1047)
* feat: add dependency manager (#1063)

### Bug Fixes
* fix: unwrapping dictionaries not working in marshaling preset (#855)
* fix: import path of helpers in DartRenderer (#794)
* fix: modelina cannot be used in website environments (#843)
* fix: duplicate dependencies being rendered (#842)
* fix: inner references not being found (#844)
* fix: root level references are not handled for JSON Schema (#829)
* fix: wrong typescript number type used for integers (#902)
* fix: merging CommonModel properties should not carry over properties to other models (#917)
* fix: duplicate and self dependencies should not be rendered (#903)
* fix: python generates unusable class for empty properties (#901)
* fix: javascript should not split out enums (#926)
* fix: typescript marshaling preset not caring about external models (#927)
* fix: typescript rendering wrong array type when union (#928)
* fix: java dictionary constrainer gives unusable integer type for map value (#929)
* fix: remove unintended characters for typescript marshaling preset (#935)
* fix: enable processor options to be passed processors (#920)
* fix: references are getting incorrect model names (#951)
* fix: enum generator for Java should use strict types for it's values (#944)
* fix: implicit python import error (#981)
* fix: rust compile errors on enum members containing digits (#994)
* fix: add `exec` as a reserved keyword for Python (#1000)
* fix: c# newtonsoft preset syntax errors (#1004)
* fix: rust enum renderer only working for JSON Schema inputs (#1001)
* fix: dependencies are rendered twice (#1002)
* fix: rust impl new fn for Boxed values (#1013)
* fix: solving blackbox tests problems (#905)
* fix: structs missing pub keyword in RustGenerator (#1021)
* fix: reserved keywords in Rust should be case-sensitive (#1031)
* fix: pattern properties not being accounted for (#1006)
* fix: csharp generator does not render optional types for optional properties (#1051)
* fix: polymorphic / union models rendered with index in enum member name (#1056)
* fix: add Jackson annotations at the field level (#1059)
* fix: improve integration with old AsyncAPI parser (#1050)
* fix: add Java constraints annotations at the field level (#1067)
* fix: java generator could generate illegal package names (#1084)

### Other Changes
* docs: new core data model (#530)
* refactor: introduce new core models (#655)
* refactor: add CommonModel conversion to MetaModel (#677)
* refactor: add TypeScript constrainer (#683)
* refactor: add JavaScript constrainer (#693)
* refactor: add Go constrainer (#695)
* refactor: add splitter (#676)
* refactor: add C# constrainer (#696)
* refactor: add Java constrainer (#694)
* refactor: simplified constraints and type mapping (#725)
* refactor: convert CSharp to new constraint setup (#735)
* refactor: convert Go to new constraint setup (#732)
* refactor: convert TS to new constraint setup (#736)
* refactor: convert JS to new constraint setup (#741)
* refactor: add object property model (#758)
* chore: refactored model setup to support generators (#766)
* chore: refactored input processors (#767)
* chore: refactored TypeScript and generator implementation (#765)
* chore: refactored Java to new core model (#769)
* chore: refactored Go generator (#771)
* chore: refactored CSharp generator (#770)
* chore: refactored JavaScript generator  (#773)
* chore: refactored dart generator (#778)
* chore: fix build errors (#779)
* chore: fix file generator tests (#782)
* chore: add test and fix constrain implementation (#781)
* chore: fix wrongful import (#783)
* refactor: switch interpretation of pattern properties (#791)
* refactor: fix constrain helpers and add test (#792)
* chore: convert to any model from common model (#793)
* chore: remove old post interpreter and fix tests (#795)
* chore: fix TypeHelpers tests (#802)
* chore: fix generator and renderer tests (#803)
* chore: remove unnecessary common model test (#798)
* chore: remove name helpers (#801)
* chore: fix tests for OutputModel (#800)
* chore: give constrained properties access to the raw property (#799)
* chore: fix enum model conversion (#797)
* chore: fix contains property check failing (#810)
* chore: removed unused property and fix general tests (#809)
* chore: refactor dart generators and test (#796)
* chore: rewrite java generator tests (#804)
* chore: rewrite TypeScript generator tests (#806)
* chore: rewrite CSharp generator tests (#807)
* chore: rewrite javascript generator tests (#805)
* fix: remaining test and implementation issues (#824)
* docs: move banner location (#865)
* docs: update language documentation (#862)
* docs: add migration guidelines (#860)
* docs: update input processing documentation (#859)
* docs: update constraint documentation (#858)
* chore: remove unused functions (#849)
* docs: update usage documentation (#857)
* docs: update preset documentation (#861)
* refactor: simplified example tests (#868)
* chore: add a template for new generators (#850)
* docs: remove duplicate dart output (#892)
* test: update snapshot for failing test (#907)
* chore: add a new example for json-schema-draft4-from-object (#897)
* chore: add a new example for JSON schema draft 6 (#933)
* ci: use @swc/jest to speedup tests (#938)
* ci: fix broken release pipeline (#956)
* docs: add contribution guidelines for processors (#950)
* chore: add missing test dependency for docker (#992)
* docs: add contributing guidelines for presets (#990)
* docs: improve readme with use-cases and examples (#1034)
* chore: add missing blackbox scripts (#1046)
* docs: add versioning and maintenance section (#991)
* test: update snapshots (#1064)
* docs: fix the wrong link to constraint example (#1065)
* test: added example to generate all models within the same file (#1054)
* chore: added prettier config (#838)
* chore: format code (#1088)


Co-authored-by: Kenneth Aasan <k.aasan@sportradar.com>, Co-authored-by: Leigh Johnson <hi@leighjohnson.me>, Co-authored-by: Maciej Urbańczyk <urbanczyk.maciej.95@gmail.com>, Co-authored-by: Nitin Tejuja <95347924+nitintejuja@users.noreply.github.com>, Co-authored-by: Amit Kumar Sharma <ksamit1110@gmail.com>, Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>, Co-authored-by: Andrey Zaytsev <zaytsevand@outlook.com>, Co-authored-by: Zbigniew Malcherczyk <zmalcherczyk@gmail.com>, Co-authored-by: Yushi OMOTE <yushiomote@gmail.com>, Co-authored-by: Alejandra Quetzalli  <alejandra.quetzalli@postman.com>, Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>, Co-authored-by: Julian R <mail@julianrapp.de>, Co-authored-by: Anay Sarkar <53341181+anaysarkar7@users.noreply.github.com>, Co-authored-by: Louis Xhaferi <louis.xhaferi@gmx.de>, Co-authored-by: Akshat Nema <76521428+akshatnema@users.noreply.github.com>
jonaslagoni added a commit that referenced this pull request Jan 24, 2023
## [1.0.0](v0.59.9...v1.0.0) (2023-01-23)

### Upgrade Steps

You can find the migration details here: https://github.com/asyncapi/modelina/blob/master/docs/migration.md 

Dont hesitate to reach out if you need help migrating to version 1.

### Breaking Changes
There is no specific PR that contains the breaking changes but is part of multiple PRs. See the migration part above.

### New Features
* feat: add Rust Generator (#818)
* feat: add Kotlin model generator (#1074)
* feat: add Python generator (#863)
* feat: add jsonbinpack preset for TypeScript (#854)
* feat: add support for AsyncAPI 2.5 (#893)
* feat: add support for oneOf and anyOf as UnionModel (#899)
* feat: integrate new AsyncAPI parser version (#925)
* feat: add C# Newtonsoft preset (#970)
* feat: add access to entire property object in constrainer (#985)
* feat: add precise csharp enum type (#1047)
* feat: add dependency manager (#1063)

### Bug Fixes
* fix: unwrapping dictionaries not working in marshaling preset (#855)
* fix: import path of helpers in DartRenderer (#794)
* fix: modelina cannot be used in website environments (#843)
* fix: duplicate dependencies being rendered (#842)
* fix: inner references not being found (#844)
* fix: root level references are not handled for JSON Schema (#829)
* fix: wrong typescript number type used for integers (#902)
* fix: merging CommonModel properties should not carry over properties to other models (#917)
* fix: duplicate and self dependencies should not be rendered (#903)
* fix: python generates unusable class for empty properties (#901)
* fix: javascript should not split out enums (#926)
* fix: typescript marshaling preset not caring about external models (#927)
* fix: typescript rendering wrong array type when union (#928)
* fix: java dictionary constrainer gives unusable integer type for map value (#929)
* fix: remove unintended characters for typescript marshaling preset (#935)
* fix: enable processor options to be passed processors (#920)
* fix: references are getting incorrect model names (#951)
* fix: enum generator for Java should use strict types for it's values (#944)
* fix: implicit python import error (#981)
* fix: rust compile errors on enum members containing digits (#994)
* fix: add `exec` as a reserved keyword for Python (#1000)
* fix: c# newtonsoft preset syntax errors (#1004)
* fix: rust enum renderer only working for JSON Schema inputs (#1001)
* fix: dependencies are rendered twice (#1002)
* fix: rust impl new fn for Boxed values (#1013)
* fix: solving blackbox tests problems (#905)
* fix: structs missing pub keyword in RustGenerator (#1021)
* fix: reserved keywords in Rust should be case-sensitive (#1031)
* fix: pattern properties not being accounted for (#1006)
* fix: csharp generator does not render optional types for optional properties (#1051)
* fix: polymorphic / union models rendered with index in enum member name (#1056)
* fix: add Jackson annotations at the field level (#1059)
* fix: improve integration with old AsyncAPI parser (#1050)
* fix: add Java constraints annotations at the field level (#1067)
* fix: java generator could generate illegal package names (#1084)

### Other Changes
* docs: new core data model (#530)
* refactor: introduce new core models (#655)
* refactor: add CommonModel conversion to MetaModel (#677)
* refactor: add TypeScript constrainer (#683)
* refactor: add JavaScript constrainer (#693)
* refactor: add Go constrainer (#695)
* refactor: add splitter (#676)
* refactor: add C# constrainer (#696)
* refactor: add Java constrainer (#694)
* refactor: simplified constraints and type mapping (#725)
* refactor: convert CSharp to new constraint setup (#735)
* refactor: convert Go to new constraint setup (#732)
* refactor: convert TS to new constraint setup (#736)
* refactor: convert JS to new constraint setup (#741)
* refactor: add object property model (#758)
* chore: refactored model setup to support generators (#766)
* chore: refactored input processors (#767)
* chore: refactored TypeScript and generator implementation (#765)
* chore: refactored Java to new core model (#769)
* chore: refactored Go generator (#771)
* chore: refactored CSharp generator (#770)
* chore: refactored JavaScript generator  (#773)
* chore: refactored dart generator (#778)
* chore: fix build errors (#779)
* chore: fix file generator tests (#782)
* chore: add test and fix constrain implementation (#781)
* chore: fix wrongful import (#783)
* refactor: switch interpretation of pattern properties (#791)
* refactor: fix constrain helpers and add test (#792)
* chore: convert to any model from common model (#793)
* chore: remove old post interpreter and fix tests (#795)
* chore: fix TypeHelpers tests (#802)
* chore: fix generator and renderer tests (#803)
* chore: remove unnecessary common model test (#798)
* chore: remove name helpers (#801)
* chore: fix tests for OutputModel (#800)
* chore: give constrained properties access to the raw property (#799)
* chore: fix enum model conversion (#797)
* chore: fix contains property check failing (#810)
* chore: removed unused property and fix general tests (#809)
* chore: refactor dart generators and test (#796)
* chore: rewrite java generator tests (#804)
* chore: rewrite TypeScript generator tests (#806)
* chore: rewrite CSharp generator tests (#807)
* chore: rewrite javascript generator tests (#805)
* fix: remaining test and implementation issues (#824)
* docs: move banner location (#865)
* docs: update language documentation (#862)
* docs: add migration guidelines (#860)
* docs: update input processing documentation (#859)
* docs: update constraint documentation (#858)
* chore: remove unused functions (#849)
* docs: update usage documentation (#857)
* docs: update preset documentation (#861)
* refactor: simplified example tests (#868)
* chore: add a template for new generators (#850)
* docs: remove duplicate dart output (#892)
* test: update snapshot for failing test (#907)
* chore: add a new example for json-schema-draft4-from-object (#897)
* chore: add a new example for JSON schema draft 6 (#933)
* ci: use @swc/jest to speedup tests (#938)
* ci: fix broken release pipeline (#956)
* docs: add contribution guidelines for processors (#950)
* chore: add missing test dependency for docker (#992)
* docs: add contributing guidelines for presets (#990)
* docs: improve readme with use-cases and examples (#1034)
* chore: add missing blackbox scripts (#1046)
* docs: add versioning and maintenance section (#991)
* test: update snapshots (#1064)
* docs: fix the wrong link to constraint example (#1065)
* test: added example to generate all models within the same file (#1054)
* chore: added prettier config (#838)
* chore: format code (#1088)


Co-authored-by: Kenneth Aasan <k.aasan@sportradar.com>
Co-authored-by: Leigh Johnson <hi@leighjohnson.me>
Co-authored-by: Maciej Urbańczyk <urbanczyk.maciej.95@gmail.com>
Co-authored-by: Nitin Tejuja <95347924+nitintejuja@users.noreply.github.com>
Co-authored-by: Amit Kumar Sharma <ksamit1110@gmail.com>
Co-authored-by: artur-ciocanu <artur.ciocanu@gmail.com>
Co-authored-by: Andrey Zaytsev <zaytsevand@outlook.com>
Co-authored-by: Zbigniew Malcherczyk <zmalcherczyk@gmail.com>
Co-authored-by: Yushi OMOTE <yushiomote@gmail.com>
Co-authored-by: Alejandra Quetzalli  <alejandra.quetzalli@postman.com>
Co-authored-by: Artur Ciocanu <ciocanu@adobe.com>
Co-authored-by: Julian R <mail@julianrapp.de>
Co-authored-by: Anay Sarkar <53341181+anaysarkar7@users.noreply.github.com>
Co-authored-by: Louis Xhaferi <louis.xhaferi@gmx.de>
Co-authored-by: Akshat Nema <76521428+akshatnema@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants