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(map): codegen map rust #87

Merged
merged 3 commits into from
Jan 30, 2024
Merged
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
61 changes: 59 additions & 2 deletions lib/codegen/fromcto/rust/rustvisitor.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,14 @@ class RustVisitor {
.forEach(namespace => {
parameters.fileWriter.writeLine(0, `use crate::${this.toValidRustName(namespace)}::*;`);
});

const hasMapDeclaration = modelFile.getAllDeclarations()
.find(declaration => declaration.isMapDeclaration?.());

if (hasMapDeclaration) {
parameters.fileWriter.writeLine(0, 'use std::collections::HashMap;');
}

parameters.fileWriter.writeLine(0, 'use crate::utils::*;');
parameters.fileWriter.writeLine(1, '');
modelFile.getAllDeclarations().forEach((declaration) => {
Expand Down Expand Up @@ -212,7 +220,7 @@ class RustVisitor {
parameters.fileWriter.writeLine(2, `rename = "${field.name}",`);
if (field.isOptional?.()) {
parameters.fileWriter.writeLine(2, 'skip_serializing_if = "Option::is_none",');
type = `Option<${type}>`;
type = this.wrapAsOption(type);
}
if (this.isDateField(field.type)) {
if (field.isOptional?.()) {
Expand All @@ -225,10 +233,57 @@ class RustVisitor {
}
}
parameters.fileWriter.writeLine(1, ')]');

if (!ModelUtil.isPrimitiveType(field.type) && ModelUtil.isMap(field)) {
const mapDeclaration = field.getModelFile().getType(field.getType());
const mapKeyType = mapDeclaration.getKey().getType();
const mapValueType = mapDeclaration.getValue().getType();

let rustKeyType;
let rustValueType;

// Key
if (ModelUtil.isPrimitiveType(mapKeyType)) {
rustKeyType = this.toRustType(mapKeyType);
} else if (ModelUtil.isScalar(mapDeclaration.getKey())) {
const scalarDeclaration = mapDeclaration.getModelFile().getType(mapDeclaration.getKey().getType());
const scalarType = scalarDeclaration.getType();
rustKeyType = this.toRustType(scalarType);
}
// Value
if (ModelUtil.isPrimitiveType(mapValueType)) {
rustValueType = this.toRustType(mapValueType);
} else if (ModelUtil.isScalar(mapDeclaration.getValue())) {
const scalarDeclaration = mapDeclaration.getModelFile().getType(mapDeclaration.getValue().getType());
const scalarType = scalarDeclaration.getType();
rustValueType = this.toRustType(scalarType);
} else {
rustValueType = mapValueType;
}

if (field.isOptional?.()) {
const optionType = this.wrapAsOption(`HashMap<${rustKeyType}, ${rustValueType}>`);
parameters.fileWriter.writeLine(1, `pub ${this.toValidRustName(field.getName())}: ${optionType},`);
} else {
parameters.fileWriter.writeLine(1, `pub ${this.toValidRustName(field.getName())}: HashMap<${rustKeyType}, ${rustValueType}>,`);
}

return null;
}

parameters.fileWriter.writeLine(1, `pub ${this.toValidRustName(field.name)}: ${type},`);
return null;
}

/**
* @param {String} type - the type to be wrapped as option
* @return {String} - the wrapped type
* @private
*/
wrapAsOption(type) {
return `Option<${type}>`;
}

/**
* Visitor design pattern
* @param {EnumDeclaration} enumDeclaration - the object being visited
Expand Down Expand Up @@ -293,7 +348,9 @@ class RustVisitor {
case 'Boolean':
return 'bool';
case 'Long':
return 'u64';
return 'i64';
Copy link
Contributor Author

@ekarademir ekarademir Jan 30, 2024

Choose a reason for hiding this comment

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

These changes basically follow what we do in Go, Java, and C# and the corresponding primitive types in Java.

I'm not sure if this will count as breaking change (probably they do) and we need to up a major version just for that.

Copy link
Member

Choose a reason for hiding this comment

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

This is a bug fix, IMO. The concerto spec says that Long values are signed, and previously these values are unsighed.

We also have the long-standing issue around the representation of Longs in JavaScript. accordproject/concerto#189

case 'Integer':
return 'i32';
case 'Double':
return 'f64';
default: {
Expand Down
56 changes: 30 additions & 26 deletions test/codegen/__snapshots__/codegen.js.snap
Original file line number Diff line number Diff line change
Expand Up @@ -4406,6 +4406,7 @@ exports[`codegen #formats check we can convert all formats from namespace unvers
use chrono::{ DateTime, TimeZone, Utc };

use crate::concerto_1_0_0::*;
use std::collections::HashMap;
use crate::utils::*;

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -4480,6 +4481,7 @@ use chrono::{ DateTime, TimeZone, Utc };

use crate::org_acme_hr_base::*;
use crate::concerto_1_0_0::*;
use std::collections::HashMap;
use crate::utils::*;

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -4503,31 +4505,31 @@ pub struct Company {
rename = "companyProperties",
skip_serializing_if = "Option::is_none",
)]
pub company_properties: Option<CompanyProperties>,
pub company_properties: Option<HashMap<String, String>>,

#[serde(
rename = "employeeDirectory",
skip_serializing_if = "Option::is_none",
)]
pub employee_directory: Option<EmployeeDirectory>,
pub employee_directory: Option<HashMap<String, Employee>>,

#[serde(
rename = "employeeTShirtSizes",
skip_serializing_if = "Option::is_none",
)]
pub employee_t_shirt_sizes: Option<EmployeeTShirtSizes>,
pub employee_t_shirt_sizes: Option<HashMap<String, TShirtSizeType>>,

#[serde(
rename = "employeeProfiles",
skip_serializing_if = "Option::is_none",
)]
pub employee_profiles: Option<EmployeeProfiles>,
pub employee_profiles: Option<HashMap<String, Concept>>,

#[serde(
rename = "employeeSocialSecurityNumbers",
skip_serializing_if = "Option::is_none",
)]
pub employee_social_security_numbers: Option<EmployeeSocialSecurityNumbers>,
pub employee_social_security_numbers: Option<HashMap<String, String>>,
}

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -4648,7 +4650,7 @@ pub struct Person {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand All @@ -4671,12 +4673,12 @@ pub struct Employee {
#[serde(
rename = "salary",
)]
pub salary: u64,
pub salary: i64,

#[serde(
rename = "numDependents",
)]
pub num_dependents: Integer,
pub num_dependents: i32,

#[serde(
rename = "retired",
Expand Down Expand Up @@ -4747,7 +4749,7 @@ pub struct Employee {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand Down Expand Up @@ -4816,7 +4818,7 @@ pub struct Contractor {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand All @@ -4842,12 +4844,12 @@ pub struct Manager {
#[serde(
rename = "salary",
)]
pub salary: u64,
pub salary: i64,

#[serde(
rename = "numDependents",
)]
pub num_dependents: Integer,
pub num_dependents: i32,

#[serde(
rename = "retired",
Expand Down Expand Up @@ -4918,7 +4920,7 @@ pub struct Manager {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand Down Expand Up @@ -10554,6 +10556,7 @@ exports[`codegen #formats check we can convert all formats from namespace versio
use chrono::{ DateTime, TimeZone, Utc };

use crate::concerto_1_0_0::*;
use std::collections::HashMap;
use crate::utils::*;

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -10628,6 +10631,7 @@ use chrono::{ DateTime, TimeZone, Utc };

use crate::org_acme_hr_base_1_0_0::*;
use crate::concerto_1_0_0::*;
use std::collections::HashMap;
use crate::utils::*;

#[derive(Debug, Serialize, Deserialize)]
Expand All @@ -10651,31 +10655,31 @@ pub struct Company {
rename = "companyProperties",
skip_serializing_if = "Option::is_none",
)]
pub company_properties: Option<CompanyProperties>,
pub company_properties: Option<HashMap<String, String>>,

#[serde(
rename = "employeeDirectory",
skip_serializing_if = "Option::is_none",
)]
pub employee_directory: Option<EmployeeDirectory>,
pub employee_directory: Option<HashMap<String, Employee>>,

#[serde(
rename = "employeeTShirtSizes",
skip_serializing_if = "Option::is_none",
)]
pub employee_t_shirt_sizes: Option<EmployeeTShirtSizes>,
pub employee_t_shirt_sizes: Option<HashMap<String, TShirtSizeType>>,

#[serde(
rename = "employeeProfiles",
skip_serializing_if = "Option::is_none",
)]
pub employee_profiles: Option<EmployeeProfiles>,
pub employee_profiles: Option<HashMap<String, Concept>>,

#[serde(
rename = "employeeSocialSecurityNumbers",
skip_serializing_if = "Option::is_none",
)]
pub employee_social_security_numbers: Option<EmployeeSocialSecurityNumbers>,
pub employee_social_security_numbers: Option<HashMap<String, String>>,
}

#[derive(Debug, Serialize, Deserialize)]
Expand Down Expand Up @@ -10796,7 +10800,7 @@ pub struct Person {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand All @@ -10819,12 +10823,12 @@ pub struct Employee {
#[serde(
rename = "salary",
)]
pub salary: u64,
pub salary: i64,

#[serde(
rename = "numDependents",
)]
pub num_dependents: Integer,
pub num_dependents: i32,

#[serde(
rename = "retired",
Expand Down Expand Up @@ -10895,7 +10899,7 @@ pub struct Employee {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand Down Expand Up @@ -10964,7 +10968,7 @@ pub struct Contractor {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand All @@ -10990,12 +10994,12 @@ pub struct Manager {
#[serde(
rename = "salary",
)]
pub salary: u64,
pub salary: i64,

#[serde(
rename = "numDependents",
)]
pub num_dependents: Integer,
pub num_dependents: i32,

#[serde(
rename = "retired",
Expand Down Expand Up @@ -11066,7 +11070,7 @@ pub struct Manager {
#[serde(
rename = "nextOfKin",
)]
pub next_of_kin: NextOfKin,
pub next_of_kin: HashMap<String, String>,

#[serde(
rename = "$identifier",
Expand Down
Loading
Loading