@@ -381,6 +381,24 @@ fn get_bufferfish_write_fn(ty: Type, value_accessor: &str) -> String {
381381 }
382382 }
383383
384+ if path. segments . len ( ) == 1
385+ && path. segments [ 0 ] . ident == "Option"
386+ && let PathArguments :: AngleBracketed ( ref args) = path. segments [ 0 ] . arguments
387+ && let Some ( GenericArgument :: Type ( inner_ty) ) = args. args . first ( )
388+ {
389+ let inner_write_call = if is_primitive_type ( inner_ty) {
390+ let inner_write_fn = get_element_write_fn ( inner_ty. clone ( ) ) ;
391+ format ! ( "bf.{inner_write_fn}({value_accessor})" )
392+ } else {
393+ let inner_write_fn = get_element_write_fn ( inner_ty. clone ( ) ) ;
394+ format ! ( "{inner_write_fn}(bf, {value_accessor})" )
395+ } ;
396+
397+ return format ! (
398+ "if ({value_accessor} !== null) {{\n bf.writeUint8(1)\n {inner_write_call}\n }} else {{\n bf.writeUint8(0)\n }}" ,
399+ ) ;
400+ }
401+
384402 match path. get_ident ( ) . map ( |ident| ident. to_string ( ) ) . as_deref ( ) {
385403 Some ( "u8" ) => format ! ( "bf.writeUint8({value_accessor})" ) ,
386404 Some ( "u16" ) => format ! ( "bf.writeUint16({value_accessor})" ) ,
@@ -491,6 +509,15 @@ fn get_typescript_type(ty: Type) -> String {
491509 return format ! ( "Array<{inner_ts_type}>" ) ;
492510 }
493511
512+ if path. segments . len ( ) == 1
513+ && path. segments [ 0 ] . ident == "Option"
514+ && let PathArguments :: AngleBracketed ( ref args) = path. segments [ 0 ] . arguments
515+ && let Some ( GenericArgument :: Type ( inner_ty) ) = args. args . first ( )
516+ {
517+ let inner_ts_type = get_typescript_type ( inner_ty. clone ( ) ) ;
518+ return format ! ( "{inner_ts_type} | null" ) ;
519+ }
520+
494521 match path. get_ident ( ) . map ( |ident| ident. to_string ( ) ) . as_deref ( ) {
495522 #[ rustfmt:: skip]
496523 Some ( "u8" ) | Some ( "u16" ) | Some ( "u32" ) | Some ( "i8" ) | Some ( "i16" ) | Some ( "i32" )
@@ -626,6 +653,18 @@ fn get_bufferfish_fn(ty: Type) -> String {
626653 return format ! ( "bf.readArray(() => {inner_fn}) as Array<{inner_ts_type}>" ) ;
627654 }
628655
656+ if path. segments . len ( ) == 1
657+ && path. segments [ 0 ] . ident == "Option"
658+ && let PathArguments :: AngleBracketed ( ref args) = path. segments [ 0 ] . arguments
659+ && let Some ( GenericArgument :: Type ( inner_ty) ) = args. args . first ( )
660+ {
661+ let inner_fn = get_bufferfish_fn ( inner_ty. clone ( ) ) ;
662+ let inner_ts_type = get_typescript_type ( inner_ty. clone ( ) ) ;
663+ return format ! (
664+ "(bf.readUint8() === 1 ? {inner_fn} : null) as {inner_ts_type} | null"
665+ ) ;
666+ }
667+
629668 match path. get_ident ( ) . map ( |ident| ident. to_string ( ) ) . as_deref ( ) {
630669 Some ( "u8" ) => "bf.readUint8() as number" . to_string ( ) ,
631670 Some ( "u16" ) => "bf.readUint16() as number" . to_string ( ) ,
@@ -699,6 +738,7 @@ mod tests {
699738pub enum MessageId {
700739 Join = 0,
701740 Leave,
741+ Ping,
702742 Unknown = 255,
703743}
704744
@@ -716,6 +756,12 @@ pub struct LeaveMessage;
716756#[derive(Encode)]
717757#[bufferfish(MessageId::Unknown)]
718758pub struct UnknownMessage(pub u8, pub u16);
759+
760+ #[derive(Encode, Decode)]
761+ #[bufferfish(MessageId::Ping)]
762+ pub struct PingMessage {
763+ pub timestamp: Option<u64>,
764+ }
719765 "# ;
720766
721767 let expected_output = r#"/* AUTOGENERATED BUFFERFISH FILE, DO NOT EDIT */
@@ -724,6 +770,7 @@ import { Bufferfish } from 'bufferfish'
724770export enum MessageId {
725771 Join = 0,
726772 Leave = 1,
773+ Ping = 2,
727774 Unknown = 255,
728775}
729776
@@ -770,6 +817,26 @@ export function encodeUnknownMessage(bf: Bufferfish, value: UnknownMessage): voi
770817 encodeMessageId(bf, MessageId.Unknown)
771818 bf.writeUint8(value[0])
772819 bf.writeUint16(value[1])
820+ }
821+
822+ export interface PingMessage {
823+ timestamp: bigint | null
824+ }
825+
826+ export function decodePingMessage(bf: Bufferfish): PingMessage {
827+ return {
828+ timestamp: (bf.readUint8() === 1 ? bf.readUint64() as bigint : null) as bigint | null,
829+ }
830+ }
831+
832+ export function encodePingMessage(bf: Bufferfish, value: PingMessage): void {
833+ encodeMessageId(bf, MessageId.Ping)
834+ if (value.timestamp !== null) {
835+ bf.writeUint8(1)
836+ bf.writeUint64(value.timestamp)
837+ } else {
838+ bf.writeUint8(0)
839+ }
773840}"# ;
774841
775842 let items = syn:: parse_file ( test_file)
0 commit comments