From b9cbee6d14588b6dce2d4710022eaf2e66c6096d Mon Sep 17 00:00:00 2001 From: Stephan Boyer Date: Wed, 19 Jun 2024 15:15:08 -0700 Subject: [PATCH] Demonstrate how to construct and eliminate choices --- README.md | 2 +- examples/rust/src/main.rs | 39 +++++++++++++------ examples/rust/types.t | 5 +++ examples/typescript/src/main.ts | 69 +++++++++++++++++++++++++-------- examples/typescript/types.t | 5 +++ 5 files changed, 91 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index 1bc88b89..7cd5dec7 100644 --- a/README.md +++ b/README.md @@ -223,7 +223,7 @@ The code generated for choices supports case analysis, so clients can take diffe fn handle_response(response: SendEmailResponseIn) { match response { Success => println!("The email was sent!"), - Error(message) => println!("An error occurred: {}", message), + Error(message) => println!("An error occurred: {message}"), } } ``` diff --git a/examples/rust/src/main.rs b/examples/rust/src/main.rs index a3658cae..c7df281e 100644 --- a/examples/rust/src/main.rs +++ b/examples/rust/src/main.rs @@ -6,31 +6,47 @@ use { io::{self, BufReader, BufWriter}, }, types::{ - types::{SendEmailRequestIn, SendEmailRequestOut}, + types::{ + SendEmailRequestIn, SendEmailRequestOut, SendEmailResponseIn, SendEmailResponseOut, + }, Deserialize, Serialize, }, }; -const FILE_PATH: &str = "/tmp/message"; +const REQUEST_FILE_PATH: &str = "/tmp/request"; +const RESPONSE_FILE_PATH: &str = "/tmp/response"; fn write_to_file() -> io::Result<()> { - let message = SendEmailRequestOut { + let request_message = SendEmailRequestOut { to: "typical@example.com".to_owned(), subject: "I love Typical!".to_owned(), body: "It makes serialization easy and safe.".to_owned(), }; - let file = BufWriter::new(File::create(FILE_PATH)?); - message.serialize(file) + let response_message = SendEmailResponseOut::Error("Example error".to_string()); + + let request_file = BufWriter::new(File::create(REQUEST_FILE_PATH)?); + request_message.serialize(request_file)?; + + let response_file = BufWriter::new(File::create(RESPONSE_FILE_PATH)?); + response_message.serialize(response_file) } fn read_from_file() -> io::Result<()> { - let file = BufReader::new(File::open(FILE_PATH)?); - let message = SendEmailRequestIn::deserialize(file)?; + let request_file = BufReader::new(File::open(REQUEST_FILE_PATH)?); + let request_message = SendEmailRequestIn::deserialize(request_file)?; + + let response_file = BufReader::new(File::open(RESPONSE_FILE_PATH)?); + let response_message = SendEmailResponseIn::deserialize(response_file)?; + + println!("to: {}", request_message.to); + println!("subject: {}", request_message.subject); + println!("body: {}", request_message.body); - println!("to: {}", message.to); - println!("subject: {}", message.subject); - println!("body: {}", message.body); + match response_message { + SendEmailResponseIn::Success => println!("The email was sent!"), + SendEmailResponseIn::Error(message) => println!("An error occurred: {message}"), + } Ok(()) } @@ -38,5 +54,6 @@ fn read_from_file() -> io::Result<()> { fn main() -> io::Result<()> { write_to_file()?; read_from_file()?; - remove_file(FILE_PATH) + remove_file(REQUEST_FILE_PATH)?; + remove_file(RESPONSE_FILE_PATH) } diff --git a/examples/rust/types.t b/examples/rust/types.t index c2e78890..f7d02e6b 100644 --- a/examples/rust/types.t +++ b/examples/rust/types.t @@ -3,3 +3,8 @@ struct SendEmailRequest { subject: String = 1 body: String = 2 } + +choice SendEmailResponse { + success = 0 + error: String = 1 +} diff --git a/examples/typescript/src/main.ts b/examples/typescript/src/main.ts index 9ca545fe..533eaa95 100644 --- a/examples/typescript/src/main.ts +++ b/examples/typescript/src/main.ts @@ -1,43 +1,78 @@ import { readFileSync, writeFileSync, unlinkSync } from 'fs'; -import { Types } from '../generated/types'; +import { Types, unreachable } from '../generated/types'; -const filePath = '/tmp/message'; -const { SendEmailRequest } = Types; +const requestFilePath = '/tmp/request'; +const responseFilePath = '/tmp/response'; +const { SendEmailRequest, SendEmailResponse } = Types; function writeToFile(): void { - const message = { + const requestMessage = { to: 'typical@example.com', subject: 'I love Typical!', body: 'It makes serialization easy and safe.', }; - const arrayBuffer = SendEmailRequest.serialize(message); - writeFileSync(filePath, Buffer.from(arrayBuffer)); + const responseMessage = { + error: 'Example error', + }; + + const requestArrayBuffer = SendEmailRequest.serialize(requestMessage); + writeFileSync(requestFilePath, Buffer.from(requestArrayBuffer)); + + const responseArrayBuffer = SendEmailResponse.serialize(responseMessage); + writeFileSync(responseFilePath, Buffer.from(responseArrayBuffer)); } function readFromFile(): void { - const fileContents = readFileSync(filePath); - const message = SendEmailRequest.deserialize( + const requestFileContents = readFileSync(requestFilePath); + const requestMessage = SendEmailRequest.deserialize( + new DataView( + requestFileContents.buffer, + requestFileContents.byteOffset, + requestFileContents.byteLength, + ), + ); + + if (requestMessage instanceof Error) { + throw requestMessage; + } + + const responseFileContents = readFileSync(responseFilePath); + const responseMessage = SendEmailResponse.deserialize( new DataView( - fileContents.buffer, - fileContents.byteOffset, - fileContents.byteLength, + responseFileContents.buffer, + responseFileContents.byteOffset, + responseFileContents.byteLength, ), ); - if (message instanceof Error) { - throw message; + if (responseMessage instanceof Error) { + throw responseMessage; } /* eslint-disable no-console -- Allow logging for this example. */ - console.log('to:', message.to); - console.log('subject:', message.subject); - console.log('body:', message.body); + console.log('to:', requestMessage.to); + console.log('subject:', requestMessage.subject); + console.log('body:', requestMessage.body); + + switch (responseMessage.$field) { + case 'success': + console.log('The email was sent!'); + break; + case 'error': + console.log('An error occurred:', responseMessage.error); + break; + default: + return unreachable(responseMessage); + } /* eslint-enable no-console -- Re-enable this rule. */ + + return undefined; // To satisfy ESLint's `consistent-return` rule } writeToFile(); readFromFile(); -unlinkSync(filePath); +unlinkSync(requestFilePath); +unlinkSync(responseFilePath); diff --git a/examples/typescript/types.t b/examples/typescript/types.t index c2e78890..f7d02e6b 100644 --- a/examples/typescript/types.t +++ b/examples/typescript/types.t @@ -3,3 +3,8 @@ struct SendEmailRequest { subject: String = 1 body: String = 2 } + +choice SendEmailResponse { + success = 0 + error: String = 1 +}