diff --git a/rust/tests/baseline_enum_from_str.rs b/rust/tests/baseline_enum_from_str.rs new file mode 100644 index 0000000000..4e52fd4bf9 --- /dev/null +++ b/rust/tests/baseline_enum_from_str.rs @@ -0,0 +1,21 @@ +use examples_baseline::{ + boost_type::BoostType, +}; + +#[test] +fn test_boost_type_from_str() -> Result<(), ()> { + assert_eq!("TURBO".parse::()?, BoostType::TURBO, "Parse \"TURBO\" as BoostType"); + assert_eq!("SUPERCHARGER".parse::()?, BoostType::SUPERCHARGER, "Parse \"SUPERCHARGER\" as BoostType"); + assert_eq!("NITROUS".parse::()?, BoostType::NITROUS, "Parse \"NITROUS\" as BoostType"); + assert_eq!("KERS".parse::()?, BoostType::KERS, "Parse \"KERS\" as BoostType"); + + assert_eq!("Turbo".parse::()?, BoostType::NullVal, "Parse \"Turbo\" as BoostType"); + assert_eq!("Supercharger".parse::()?, BoostType::NullVal, "Parse \"Supercharger\" as BoostType"); + assert_eq!("Nitrous".parse::()?, BoostType::NullVal, "Parse \"Nitrous\" as BoostType"); + assert_eq!("Kers".parse::()?, BoostType::NullVal, "Parse \"Kers\" as BoostType"); + + assert_eq!("AA".parse::()?, BoostType::NullVal, "Parse \"AA\" as BoostType"); + assert_eq!("".parse::().unwrap(), BoostType::NullVal, "Parse \"\" as BoostType"); + + Ok(()) +} diff --git a/rust/tests/baseline_enum_into.rs b/rust/tests/baseline_enum_into.rs new file mode 100644 index 0000000000..9580e51b0d --- /dev/null +++ b/rust/tests/baseline_enum_into.rs @@ -0,0 +1,14 @@ +use examples_baseline::{ + boost_type::BoostType, +}; + +#[test] +fn test_boost_type_from_str() -> Result<(), ()> { + assert_eq!(>::into(BoostType::TURBO), 84_u8, "BoostType::TURBO into value"); + assert_eq!(>::into(BoostType::SUPERCHARGER), 83_u8, "BoostType::SUPERCHARGER into value"); + assert_eq!(>::into(BoostType::NITROUS), 78_u8, "BoostType::NITROUS into value"); + assert_eq!(>::into(BoostType::KERS), 75_u8, "BoostType::KERS into value"); + assert_eq!(>::into(BoostType::NullVal), 0_u8, "BoostType::NullVal into value"); + + Ok(()) +} diff --git a/rust/tests/baseline_enum_to_str.rs b/rust/tests/baseline_enum_to_str.rs new file mode 100644 index 0000000000..93f5206517 --- /dev/null +++ b/rust/tests/baseline_enum_to_str.rs @@ -0,0 +1,14 @@ +use examples_baseline::{ + boost_type::BoostType, +}; + +#[test] +fn test_boost_type_from_str() -> Result<(), ()> { + assert_eq!(format!("{}", BoostType::TURBO), "TURBO", "Display \"TURBO\""); + assert_eq!(format!("{}", BoostType::SUPERCHARGER), "SUPERCHARGER", "Display \"SUPERCHARGER\""); + assert_eq!(format!("{}", BoostType::NITROUS), "NITROUS", "Display \"NITROUS\""); + assert_eq!(format!("{}", BoostType::KERS), "KERS", "Display \"KERS\""); + assert_eq!(format!("{}", BoostType::NullVal), "NullVal", "Display \"NullVal\""); + + Ok(()) +} diff --git a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java index 5ed04fc9fb..7c2a492ce4 100644 --- a/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java +++ b/sbe-tool/src/main/java/uk/co/real_logic/sbe/generation/rust/RustGenerator.java @@ -1266,6 +1266,24 @@ private static void generateEnum( indent(writer, 0, "}\n"); // From impl + generateFromImplForEnum(enumRustName, primitiveType, messageBody, writer); + + // Into impl + generateIntoImplForEnum(enumRustName, primitiveType, messageBody, writer); + + // FromStr impl + generateFromStrImplForEnum(enumRustName, primitiveType, messageBody, writer); + + // Display impl + generateDisplayImplForEnum(enumRustName, primitiveType, messageBody, writer); + } + + private static void generateFromImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { indent(writer, 0, "impl From<%s> for %s {\n", primitiveType, enumRustName); indent(writer, 1, "#[inline]\n"); indent(writer, 1, "fn from(v: %s) -> Self {\n", primitiveType); @@ -1285,6 +1303,76 @@ private static void generateEnum( indent(writer, 0, "}\n"); } + private static void generateIntoImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { + indent(writer, 0, "impl Into<%s> for %s {\n", primitiveType, enumRustName); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn into(self) -> %s {\n", primitiveType); + indent(writer, 2, "match self {\n"); + for (final Token token : messageBody) + { + final Encoding encoding = token.encoding(); + final String literal = generateRustLiteral(encoding.primitiveType(), encoding.constValue().toString()); + indent(writer, 3, "Self::%s => %s, \n", token.name(), literal); + } + { + final Encoding encoding = messageBody.get(0).encoding(); + final CharSequence nullVal = generateRustLiteral(encoding.primitiveType(), + encoding.applicableNullValue().toString()); + indent(writer, 3, "Self::NullVal => %s,\n", nullVal); + } + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + + private static void generateFromStrImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { + indent(writer, 0, "impl core::str::FromStr for %s {\n", enumRustName); + indent(writer, 1, "type Err = ();\n\n"); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn from_str(v: &str) -> core::result::Result {\n"); + indent(writer, 2, "match v {\n"); + for (final Token token : messageBody) + { + indent(writer, 3, "\"%1$s\" => core::result::Result::Ok(Self::%1$s), \n", token.name()); + } + // default => NullVal + indent(writer, 3, "_ => core::result::Result::Ok(Self::NullVal),\n"); + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + + private static void generateDisplayImplForEnum( + final String enumRustName, + final String primitiveType, + final List messageBody, + final Appendable writer) throws IOException + { + indent(writer, 0, "impl core::fmt::Display for %s {\n", enumRustName); + indent(writer, 1, "#[inline]\n"); + indent(writer, 1, "fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {\n"); + indent(writer, 2, "match self {\n"); + for (final Token token : messageBody) + { + indent(writer, 3, "Self::%1$s => write!(f, \"%1$s\"), \n", token.name()); + } + // default => Err + indent(writer, 3, "Self::NullVal => write!(f, \"NullVal\"),\n"); + indent(writer, 2, "}\n"); + indent(writer, 1, "}\n"); + indent(writer, 0, "}\n"); + } + private static void generateComposites( final String schemaVersionType, final Ir ir,