@@ -3403,6 +3403,71 @@ pub struct Text {
34033403 flags : u32 ,
34043404 variant : TextVariant ,
34053405}
3406+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Serialize , Deserialize ) ]
3407+ #[ repr( i8 ) ]
3408+ pub enum EDateTimeStyle {
3409+ Default = 0 ,
3410+ Short = 1 ,
3411+ Medium = 2 ,
3412+ Long = 3 ,
3413+ Full = 4 ,
3414+ Custom = 5 ,
3415+ }
3416+ impl EDateTimeStyle {
3417+ fn from_i8 ( value : i8 ) -> Result < Self > {
3418+ Ok ( match value {
3419+ 0 => Self :: Default ,
3420+ 1 => Self :: Short ,
3421+ 2 => Self :: Medium ,
3422+ 3 => Self :: Long ,
3423+ 4 => Self :: Full ,
3424+ 5 => Self :: Custom ,
3425+ _ => {
3426+ return Err ( Error :: Other ( format ! ( "unknown EDateTimeStyle 0x{value:x}" ) ) ) ;
3427+ }
3428+ } )
3429+ }
3430+ }
3431+
3432+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Serialize , Deserialize ) ]
3433+ #[ repr( u8 ) ]
3434+ pub enum ETextTransformType {
3435+ ToLower = 0 ,
3436+ ToUpper = 1 ,
3437+ }
3438+ impl ETextTransformType {
3439+ fn from_u8 ( value : u8 ) -> Result < Self > {
3440+ Ok ( match value {
3441+ 0 => Self :: ToLower ,
3442+ 1 => Self :: ToUpper ,
3443+ _ => {
3444+ return Err ( Error :: Other ( format ! (
3445+ "unknown ETextTransformType 0x{value:x}"
3446+ ) ) ) ;
3447+ }
3448+ } )
3449+ }
3450+ }
3451+
3452+ #[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
3453+ pub struct FFormatNamedArgument {
3454+ name : String ,
3455+ value : FFormatArgumentValue ,
3456+ }
3457+ impl FFormatNamedArgument {
3458+ fn read < A : ArchiveReader > ( ar : & mut A ) -> Result < Self > {
3459+ Ok ( Self {
3460+ name : ar. read_string ( ) ?,
3461+ value : FFormatArgumentValue :: read ( ar) ?,
3462+ } )
3463+ }
3464+ fn write < A : ArchiveWriter > ( & self , ar : & mut A ) -> Result < ( ) > {
3465+ ar. write_string ( & self . name ) ?;
3466+ self . value . write ( ar) ?;
3467+ Ok ( ( ) )
3468+ }
3469+ }
3470+
34063471#[ derive( Debug , Clone , PartialEq , Serialize , Deserialize ) ]
34073472pub enum TextVariant {
34083473 // -0x1
@@ -3415,6 +3480,16 @@ pub enum TextVariant {
34153480 key : String ,
34163481 source_string : String ,
34173482 } ,
3483+ // 0x1
3484+ NamedFormat {
3485+ format_text : std:: boxed:: Box < Text > ,
3486+ arguments : Vec < FFormatNamedArgument > ,
3487+ } ,
3488+ // 0x2
3489+ OrderedFormat {
3490+ format_text : std:: boxed:: Box < Text > ,
3491+ arguments : Vec < FFormatArgumentValue > ,
3492+ } ,
34183493 // 0x3
34193494 ArgumentFormat {
34203495 // aka ArgumentDataFormat
@@ -3427,18 +3502,58 @@ pub enum TextVariant {
34273502 format_options : Option < FNumberFormattingOptions > ,
34283503 culture_name : String ,
34293504 } ,
3505+ // 0x5
3506+ AsPercent {
3507+ source_value : FFormatArgumentValue ,
3508+ format_options : Option < FNumberFormattingOptions > ,
3509+ culture_name : String ,
3510+ } ,
3511+ // 0x6
3512+ AsCurrency {
3513+ currency_code : String ,
3514+ source_value : FFormatArgumentValue ,
3515+ format_options : Option < FNumberFormattingOptions > ,
3516+ culture_name : String ,
3517+ } ,
34303518 // 0x7
34313519 AsDate {
34323520 source_date_time : DateTime ,
3433- date_style : i8 , // TODO EDateTimeStyle::Type
3521+ date_style : EDateTimeStyle ,
3522+ time_zone : String ,
3523+ culture_name : String ,
3524+ } ,
3525+ // 0x8
3526+ AsTime {
3527+ source_date_time : DateTime ,
3528+ time_style : EDateTimeStyle ,
34343529 time_zone : String ,
34353530 culture_name : String ,
34363531 } ,
3532+ // 0x9
3533+ AsDateTime {
3534+ source_date_time : DateTime ,
3535+ date_style : EDateTimeStyle ,
3536+ time_style : EDateTimeStyle ,
3537+ /// Only present when `date_style` is `EDateTimeStyle::Custom`.
3538+ custom_pattern : Option < String > ,
3539+ time_zone : String ,
3540+ culture_name : String ,
3541+ } ,
3542+ // 0xa
3543+ Transform {
3544+ source_text : std:: boxed:: Box < Text > ,
3545+ transform_type : ETextTransformType ,
3546+ } ,
3547+ // 0xb
34373548 StringTableEntry {
3438- // 0xb
34393549 table : String ,
34403550 key : String ,
34413551 } ,
3552+ // 0xc
3553+ TextGenerator {
3554+ generator_type_id : String ,
3555+ generator_contents : Vec < u8 > ,
3556+ } ,
34423557}
34433558
34443559impl Text {
@@ -3457,6 +3572,14 @@ impl Text {
34573572 key : read_string ( ar) ?,
34583573 source_string : read_string ( ar) ?,
34593574 } ) ,
3575+ 0x1 => Ok ( TextVariant :: NamedFormat {
3576+ format_text : std:: boxed:: Box :: new ( Text :: read ( ar) ?) ,
3577+ arguments : read_array ( ar. read_u32 :: < LE > ( ) ?, ar, FFormatNamedArgument :: read) ?,
3578+ } ) ,
3579+ 0x2 => Ok ( TextVariant :: OrderedFormat {
3580+ format_text : std:: boxed:: Box :: new ( Text :: read ( ar) ?) ,
3581+ arguments : read_array ( ar. read_u32 :: < LE > ( ) ?, ar, FFormatArgumentValue :: read) ?,
3582+ } ) ,
34603583 0x3 => Ok ( TextVariant :: ArgumentFormat {
34613584 format_text : std:: boxed:: Box :: new ( Text :: read ( ar) ?) ,
34623585 arguments : read_array ( ar. read_u32 :: < LE > ( ) ?, ar, FFormatArgumentData :: read) ?,
@@ -3468,17 +3591,67 @@ impl Text {
34683591 . transpose ( ) ?,
34693592 culture_name : ar. read_string ( ) ?,
34703593 } ) ,
3594+ 0x5 => Ok ( TextVariant :: AsPercent {
3595+ source_value : FFormatArgumentValue :: read ( ar) ?,
3596+ format_options : ( ar. read_u32 :: < LE > ( ) ? != 0 ) // bHasFormatOptions
3597+ . then ( || FNumberFormattingOptions :: read ( ar) )
3598+ . transpose ( ) ?,
3599+ culture_name : ar. read_string ( ) ?,
3600+ } ) ,
3601+ 0x6 => Ok ( TextVariant :: AsCurrency {
3602+ currency_code : ar. read_string ( ) ?,
3603+ source_value : FFormatArgumentValue :: read ( ar) ?,
3604+ format_options : ( ar. read_u32 :: < LE > ( ) ? != 0 ) // bHasFormatOptions
3605+ . then ( || FNumberFormattingOptions :: read ( ar) )
3606+ . transpose ( ) ?,
3607+ culture_name : ar. read_string ( ) ?,
3608+ } ) ,
34713609 0x7 => Ok ( TextVariant :: AsDate {
34723610 source_date_time : ar. read_u64 :: < LE > ( ) ?,
3473- date_style : ar. read_i8 ( ) ?,
3611+ date_style : EDateTimeStyle :: from_i8 ( ar. read_i8 ( ) ? ) ?,
34743612 time_zone : ar. read_string ( ) ?,
34753613 culture_name : ar. read_string ( ) ?,
34763614 } ) ,
3477- 0xb => Ok ( {
3478- TextVariant :: StringTableEntry {
3479- table : ar. read_string ( ) ?,
3480- key : read_string ( ar) ?,
3481- }
3615+ 0x8 => Ok ( TextVariant :: AsTime {
3616+ source_date_time : ar. read_u64 :: < LE > ( ) ?,
3617+ time_style : EDateTimeStyle :: from_i8 ( ar. read_i8 ( ) ?) ?,
3618+ time_zone : ar. read_string ( ) ?,
3619+ culture_name : ar. read_string ( ) ?,
3620+ } ) ,
3621+ 0x9 => {
3622+ let source_date_time = ar. read_u64 :: < LE > ( ) ?;
3623+ let date_style = EDateTimeStyle :: from_i8 ( ar. read_i8 ( ) ?) ?;
3624+ let time_style = EDateTimeStyle :: from_i8 ( ar. read_i8 ( ) ?) ?;
3625+ let custom_pattern = if date_style == EDateTimeStyle :: Custom {
3626+ Some ( ar. read_string ( ) ?)
3627+ } else {
3628+ None
3629+ } ;
3630+ Ok ( TextVariant :: AsDateTime {
3631+ source_date_time,
3632+ date_style,
3633+ time_style,
3634+ custom_pattern,
3635+ time_zone : ar. read_string ( ) ?,
3636+ culture_name : ar. read_string ( ) ?,
3637+ } )
3638+ }
3639+ 0xa => Ok ( TextVariant :: Transform {
3640+ source_text : std:: boxed:: Box :: new ( Text :: read ( ar) ?) ,
3641+ transform_type : ETextTransformType :: from_u8 ( ar. read_u8 ( ) ?) ?,
3642+ } ) ,
3643+ 0xb => Ok ( TextVariant :: StringTableEntry {
3644+ table : ar. read_string ( ) ?,
3645+ key : read_string ( ar) ?,
3646+ } ) ,
3647+ 0xc => Ok ( TextVariant :: TextGenerator {
3648+ generator_type_id : ar. read_string ( ) ?,
3649+ generator_contents : {
3650+ let len = ar. read_u32 :: < LE > ( ) ? as usize ;
3651+ let mut bytes = vec ! [ 0 ; len] ;
3652+ ar. read_exact ( & mut bytes) ?;
3653+ bytes
3654+ } ,
34823655 } ) ,
34833656 _ => Err ( Error :: Other ( format ! (
34843657 "unimplemented variant for FTextHistory 0x{text_history_type:x}"
@@ -3511,6 +3684,28 @@ impl Text {
35113684 write_string ( ar, key) ?;
35123685 write_string ( ar, source_string) ?;
35133686 }
3687+ TextVariant :: NamedFormat {
3688+ format_text,
3689+ arguments,
3690+ } => {
3691+ ar. write_i8 ( 0x1 ) ?;
3692+ format_text. write ( ar) ?;
3693+ ar. write_u32 :: < LE > ( arguments. len ( ) as u32 ) ?;
3694+ for a in arguments {
3695+ a. write ( ar) ?;
3696+ }
3697+ }
3698+ TextVariant :: OrderedFormat {
3699+ format_text,
3700+ arguments,
3701+ } => {
3702+ ar. write_i8 ( 0x2 ) ?;
3703+ format_text. write ( ar) ?;
3704+ ar. write_u32 :: < LE > ( arguments. len ( ) as u32 ) ?;
3705+ for a in arguments {
3706+ a. write ( ar) ?;
3707+ }
3708+ }
35143709 TextVariant :: ArgumentFormat {
35153710 format_text,
35163711 arguments,
@@ -3535,6 +3730,34 @@ impl Text {
35353730 }
35363731 ar. write_string ( culture_name) ?;
35373732 }
3733+ TextVariant :: AsPercent {
3734+ source_value,
3735+ format_options,
3736+ culture_name,
3737+ } => {
3738+ ar. write_i8 ( 0x5 ) ?;
3739+ source_value. write ( ar) ?;
3740+ ar. write_u32 :: < LE > ( format_options. is_some ( ) as u32 ) ?;
3741+ if let Some ( format_options) = format_options {
3742+ format_options. write ( ar) ?;
3743+ }
3744+ ar. write_string ( culture_name) ?;
3745+ }
3746+ TextVariant :: AsCurrency {
3747+ currency_code,
3748+ source_value,
3749+ format_options,
3750+ culture_name,
3751+ } => {
3752+ ar. write_i8 ( 0x6 ) ?;
3753+ ar. write_string ( currency_code) ?;
3754+ source_value. write ( ar) ?;
3755+ ar. write_u32 :: < LE > ( format_options. is_some ( ) as u32 ) ?;
3756+ if let Some ( format_options) = format_options {
3757+ format_options. write ( ar) ?;
3758+ }
3759+ ar. write_string ( culture_name) ?;
3760+ }
35383761 TextVariant :: AsDate {
35393762 source_date_time,
35403763 date_style,
@@ -3543,15 +3766,67 @@ impl Text {
35433766 } => {
35443767 ar. write_i8 ( 0x7 ) ?;
35453768 ar. write_u64 :: < LE > ( * source_date_time) ?;
3546- ar. write_i8 ( * date_style) ?;
3769+ ar. write_i8 ( * date_style as i8 ) ?;
35473770 ar. write_string ( time_zone) ?;
35483771 ar. write_string ( culture_name) ?;
35493772 }
3773+ TextVariant :: AsTime {
3774+ source_date_time,
3775+ time_style,
3776+ time_zone,
3777+ culture_name,
3778+ } => {
3779+ ar. write_i8 ( 0x8 ) ?;
3780+ ar. write_u64 :: < LE > ( * source_date_time) ?;
3781+ ar. write_i8 ( * time_style as i8 ) ?;
3782+ ar. write_string ( time_zone) ?;
3783+ ar. write_string ( culture_name) ?;
3784+ }
3785+ TextVariant :: AsDateTime {
3786+ source_date_time,
3787+ date_style,
3788+ time_style,
3789+ custom_pattern,
3790+ time_zone,
3791+ culture_name,
3792+ } => {
3793+ ar. write_i8 ( 0x9 ) ?;
3794+ ar. write_u64 :: < LE > ( * source_date_time) ?;
3795+ ar. write_i8 ( * date_style as i8 ) ?;
3796+ ar. write_i8 ( * time_style as i8 ) ?;
3797+ if * date_style == EDateTimeStyle :: Custom {
3798+ let pattern = custom_pattern. as_deref ( ) . ok_or_else ( || {
3799+ Error :: Other (
3800+ "AsDateTime with Custom date_style requires custom_pattern" . to_string ( ) ,
3801+ )
3802+ } ) ?;
3803+ ar. write_string ( pattern) ?;
3804+ }
3805+ ar. write_string ( time_zone) ?;
3806+ ar. write_string ( culture_name) ?;
3807+ }
3808+ TextVariant :: Transform {
3809+ source_text,
3810+ transform_type,
3811+ } => {
3812+ ar. write_i8 ( 0xa ) ?;
3813+ source_text. write ( ar) ?;
3814+ ar. write_u8 ( * transform_type as u8 ) ?;
3815+ }
35503816 TextVariant :: StringTableEntry { table, key } => {
35513817 ar. write_i8 ( 0xb ) ?;
35523818 ar. write_string ( table) ?;
35533819 write_string ( ar, key) ?;
35543820 }
3821+ TextVariant :: TextGenerator {
3822+ generator_type_id,
3823+ generator_contents,
3824+ } => {
3825+ ar. write_i8 ( 0xc ) ?;
3826+ ar. write_string ( generator_type_id) ?;
3827+ ar. write_u32 :: < LE > ( generator_contents. len ( ) as u32 ) ?;
3828+ ar. write_all ( generator_contents) ?;
3829+ }
35553830 }
35563831 Ok ( ( ) )
35573832 }
0 commit comments