From 39210fe9119e0e0a1e16911408e096885c8a62ab Mon Sep 17 00:00:00 2001 From: LIU JIE Date: Wed, 9 Oct 2024 15:02:14 +0800 Subject: [PATCH] fix: use LazyLock for const type with nonconst construction (#272) --- Cargo.lock | 3 +- pilota-build/Cargo.toml | 3 +- pilota-build/src/middle/context.rs | 20 +- pilota-build/src/symbol.rs | 69 +----- pilota-build/test_data/thrift/const_val.rs | 203 +++++++++++++++++- .../test_data/thrift/const_val.thrift | 7 + pilota-build/test_data/thrift/enum_map.rs | 14 +- pilota-build/test_data/thrift/multi.rs | 26 +-- pilota-build/test_data/unknown_fields.rs | 22 +- pilota/src/thrift/mod.rs | 4 +- 10 files changed, 253 insertions(+), 118 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 38c33a99..d1234507 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -805,7 +805,7 @@ dependencies = [ [[package]] name = "pilota-build" -version = "0.11.20" +version = "0.11.21" dependencies = [ "ahash", "anyhow", @@ -816,7 +816,6 @@ dependencies = [ "faststr", "heck 0.5.0", "itertools 0.13.0", - "lazy_static", "linkedbytes", "normpath", "paste", diff --git a/pilota-build/Cargo.toml b/pilota-build/Cargo.toml index 6545c8c1..76a95d55 100644 --- a/pilota-build/Cargo.toml +++ b/pilota-build/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "pilota-build" -version = "0.11.20" +version = "0.11.21" edition = "2021" description = "Compile thrift and protobuf idl into rust code at compile-time." documentation = "https://docs.rs/pilota-build" @@ -24,7 +24,6 @@ anyhow = "1" dashmap = "5" heck = "0.5" itertools = "0.13" -lazy_static = "1" normpath = "1" paste = "1" petgraph = "0.6" diff --git a/pilota-build/src/middle/context.rs b/pilota-build/src/middle/context.rs index d1649e1c..b224f127 100644 --- a/pilota-build/src/middle/context.rs +++ b/pilota-build/src/middle/context.rs @@ -733,6 +733,8 @@ impl Context { v = format!("Some({v})").into() } anyhow::Ok((format!("{name}: {v}"), is_const)) + } else if f.is_optional() { + anyhow::Ok((format!("{name}: None"), true)) } else { anyhow::Ok((format!("{name}: Default::default()"), false)) } @@ -770,13 +772,21 @@ impl Context { Ok(if should_lazy_static { let lit = self.lit_as_rvalue(lit, ty)?.0; format! {r#" - ::pilota::lazy_static::lazy_static! {{ - pub static ref {name}: {ty} = {lit}; - }} + pub static {name}: ::std::sync::LazyLock<{ty}> = ::std::sync::LazyLock::new(|| {{ + {lit} + }}); "#} } else { - let lit = self.lit_into_ty(lit, ty)?.0; - format!(r#"pub const {name}: {ty} = {lit};"#) + let (lit, is_const) = self.lit_into_ty(lit, ty)?; + if is_const { + format!(r#"pub const {name}: {ty} = {lit};"#) + } else { + format! {r#" + pub static {name}: ::std::sync::LazyLock<{ty}> = ::std::sync::LazyLock::new(|| {{ + {lit} + }}); + "#} + } }) } diff --git a/pilota-build/src/symbol.rs b/pilota-build/src/symbol.rs index efb0f4b6..ebe497d0 100644 --- a/pilota-build/src/symbol.rs +++ b/pilota-build/src/symbol.rs @@ -14,67 +14,14 @@ crate::newtype_index! { pub static SPECIAL_NAMINGS: OnceLock> = OnceLock::new(); -lazy_static::lazy_static! { - static ref KEYWORDS_SET: phf::Set<&'static str> = phf_set![ - "as", - "use", - "break", - "const", - "continue", - "crate", - "else", - "if", - "enum", - "extern", - "false", - "fn", - "for", - "impl", - "in", - "let", - "loop", - "match", - "mod", - "move", - "mut", - "pub", - "ref", - "return", - "Self", - "self", - "static", - "struct", - "super", - "trait", - "true", - "type", - "unsafe", - "where", - "while", - "abstract", - "alignof", - "become", - "box", - "do", - "final", - "macro", - "offsetof", - "override", - "priv", - "proc", - "pure", - "sizeof", - "typeof", - "unsized", - "virtual", - "yield", - "dyn", - "async", - "await", - "try" - ]; - -} +static KEYWORDS_SET: phf::Set<&'static str> = phf_set![ + "as", "use", "break", "const", "continue", "crate", "else", "if", "enum", "extern", "false", + "fn", "for", "impl", "in", "let", "loop", "match", "mod", "move", "mut", "pub", "ref", + "return", "Self", "self", "static", "struct", "super", "trait", "true", "type", "unsafe", + "where", "while", "abstract", "alignof", "become", "box", "do", "final", "macro", "offsetof", + "override", "priv", "proc", "pure", "sizeof", "typeof", "unsized", "virtual", "yield", "dyn", + "async", "await", "try" +]; #[derive(Hash, PartialEq, Eq, Clone, Debug, PartialOrd, Ord)] pub struct Symbol(pub FastStr); diff --git a/pilota-build/test_data/thrift/const_val.rs b/pilota-build/test_data/thrift/const_val.rs index aff6bf27..af874407 100644 --- a/pilota-build/test_data/thrift/const_val.rs +++ b/pilota-build/test_data/thrift/const_val.rs @@ -93,20 +93,203 @@ pub mod const_val { __protocol.i32_len(self.inner()) } } - ::pilota::lazy_static::lazy_static! { - pub static ref TEST_MAP_LIST: ::pilota::AHashMap> = { + pub const TEST_STRUCT: Test = Test { name: None }; + pub static TEST_MAP: ::std::sync::LazyLock<::pilota::AHashMap> = + ::std::sync::LazyLock::new(|| { + let mut map = ::pilota::AHashMap::with_capacity(2); + map.insert(Index::A, "hello"); + map.insert(Index::B, "world"); + map + }); + pub const TEST_LIST: [&'static str; 2] = ["hello", "world"]; + pub static TEST_MAP_LIST: ::std::sync::LazyLock< + ::pilota::AHashMap>, + > = ::std::sync::LazyLock::new(|| { let mut map = ::pilota::AHashMap::with_capacity(1); map.insert(1i32, ::std::vec!["hello"]); map - }; + }); + #[derive(Debug, Default, Clone, PartialEq)] + pub struct Test { + pub name: + ::std::option::Option<::pilota::AHashMap<::pilota::FastStr, ::pilota::FastStr>>, } - pub const TEST_LIST: [&'static str; 2] = ["hello", "world"]; - ::pilota::lazy_static::lazy_static! { - pub static ref TEST_MAP: ::pilota::AHashMap = { - let mut map = ::pilota::AHashMap::with_capacity(2); - map.insert(Index::A, "hello");map.insert(Index::B, "world"); - map - }; + impl ::pilota::thrift::Message for Test { + fn encode( + &self, + __protocol: &mut T, + ) -> ::std::result::Result<(), ::pilota::thrift::ThriftException> { + #[allow(unused_imports)] + use ::pilota::thrift::TOutputProtocolExt; + let struct_ident = ::pilota::thrift::TStructIdentifier { name: "Test" }; + + __protocol.write_struct_begin(&struct_ident)?; + if let Some(value) = self.name.as_ref() { + __protocol.write_map_field( + 1, + ::pilota::thrift::TType::Binary, + ::pilota::thrift::TType::Binary, + &value, + |__protocol, key| { + __protocol.write_faststr((key).clone())?; + ::std::result::Result::Ok(()) + }, + |__protocol, val| { + __protocol.write_faststr((val).clone())?; + ::std::result::Result::Ok(()) + }, + )?; + } + __protocol.write_field_stop()?; + __protocol.write_struct_end()?; + ::std::result::Result::Ok(()) + } + + fn decode( + __protocol: &mut T, + ) -> ::std::result::Result { + #[allow(unused_imports)] + use ::pilota::{thrift::TLengthProtocolExt, Buf}; + + let mut var_1 = None; + + let mut __pilota_decoding_field_id = None; + + __protocol.read_struct_begin()?; + if let ::std::result::Result::Err(mut err) = (|| { + loop { + let field_ident = __protocol.read_field_begin()?; + if field_ident.field_type == ::pilota::thrift::TType::Stop { + __protocol.field_stop_len(); + break; + } else { + __protocol.field_begin_len(field_ident.field_type, field_ident.id); + } + __pilota_decoding_field_id = field_ident.id; + match field_ident.id { + Some(1) if field_ident.field_type == ::pilota::thrift::TType::Map => { + var_1 = Some({ + let map_ident = __protocol.read_map_begin()?; + let mut val = ::pilota::AHashMap::with_capacity(map_ident.size); + for _ in 0..map_ident.size { + val.insert( + __protocol.read_faststr()?, + __protocol.read_faststr()?, + ); + } + __protocol.read_map_end()?; + val + }); + } + _ => { + __protocol.skip(field_ident.field_type)?; + } + } + + __protocol.read_field_end()?; + __protocol.field_end_len(); + } + ::std::result::Result::Ok::<_, ::pilota::thrift::ThriftException>(()) + })() { + if let Some(field_id) = __pilota_decoding_field_id { + err.prepend_msg(&format!( + "decode struct `Test` field(#{}) failed, caused by: ", + field_id + )); + } + return ::std::result::Result::Err(err); + }; + __protocol.read_struct_end()?; + + let data = Self { name: var_1 }; + ::std::result::Result::Ok(data) + } + + fn decode_async<'a, T: ::pilota::thrift::TAsyncInputProtocol>( + __protocol: &'a mut T, + ) -> ::std::pin::Pin< + ::std::boxed::Box< + dyn ::std::future::Future< + Output = ::std::result::Result, + > + Send + + 'a, + >, + > { + ::std::boxed::Box::pin(async move { + let mut var_1 = None; + + let mut __pilota_decoding_field_id = None; + + __protocol.read_struct_begin().await?; + if let ::std::result::Result::Err(mut err) = async { + loop { + let field_ident = __protocol.read_field_begin().await?; + if field_ident.field_type == ::pilota::thrift::TType::Stop { + break; + } else { + } + __pilota_decoding_field_id = field_ident.id; + match field_ident.id { + Some(1) + if field_ident.field_type == ::pilota::thrift::TType::Map => + { + var_1 = Some({ + let map_ident = __protocol.read_map_begin().await?; + let mut val = + ::pilota::AHashMap::with_capacity(map_ident.size); + for _ in 0..map_ident.size { + val.insert( + __protocol.read_faststr().await?, + __protocol.read_faststr().await?, + ); + } + __protocol.read_map_end().await?; + val + }); + } + _ => { + __protocol.skip(field_ident.field_type).await?; + } + } + + __protocol.read_field_end().await?; + } + ::std::result::Result::Ok::<_, ::pilota::thrift::ThriftException>(()) + } + .await + { + if let Some(field_id) = __pilota_decoding_field_id { + err.prepend_msg(&format!( + "decode struct `Test` field(#{}) failed, caused by: ", + field_id + )); + } + return ::std::result::Result::Err(err); + }; + __protocol.read_struct_end().await?; + + let data = Self { name: var_1 }; + ::std::result::Result::Ok(data) + }) + } + + fn size(&self, __protocol: &mut T) -> usize { + #[allow(unused_imports)] + use ::pilota::thrift::TLengthProtocolExt; + __protocol.struct_begin_len(&::pilota::thrift::TStructIdentifier { name: "Test" }) + + self.name.as_ref().map_or(0, |value| { + __protocol.map_field_len( + Some(1), + ::pilota::thrift::TType::Binary, + ::pilota::thrift::TType::Binary, + value, + |__protocol, key| __protocol.faststr_len(key), + |__protocol, val| __protocol.faststr_len(val), + ) + }) + + __protocol.field_stop_len() + + __protocol.struct_end_len() + } } } } diff --git a/pilota-build/test_data/thrift/const_val.thrift b/pilota-build/test_data/thrift/const_val.thrift index ff758be7..24f0e177 100644 --- a/pilota-build/test_data/thrift/const_val.thrift +++ b/pilota-build/test_data/thrift/const_val.thrift @@ -3,6 +3,10 @@ enum Index { B = 1, } +struct Test { + 1: map name, +} + const map TEST_MAP = { Index.A: "hello", Index.B: "world", @@ -17,4 +21,7 @@ const list TEST_LIST = [ const map> TEST_MAP_LIST = { 1: ["hello"] +} + +const Test TEST_STRUCT = { } \ No newline at end of file diff --git a/pilota-build/test_data/thrift/enum_map.rs b/pilota-build/test_data/thrift/enum_map.rs index df128ea4..0a9146e5 100644 --- a/pilota-build/test_data/thrift/enum_map.rs +++ b/pilota-build/test_data/thrift/enum_map.rs @@ -63,13 +63,13 @@ pub mod enum_map { pub const TYPE_B2: TypeB = TypeB(2i32); pub const TYPE_A1: TypeA = TypeA(::pilota::FastStr::from_static_str("a1")); pub const TYPE_B1: TypeB = TypeB(1i32); - ::pilota::lazy_static::lazy_static! { - pub static ref TYPE_A_MAP: ::pilota::AHashMap = { - let mut map = ::pilota::AHashMap::with_capacity(2); - map.insert(TYPE_B1, TYPE_A1);map.insert(TYPE_B2, TYPE_A2); - map - }; - } + pub static TYPE_A_MAP: ::std::sync::LazyLock<::pilota::AHashMap> = + ::std::sync::LazyLock::new(|| { + let mut map = ::pilota::AHashMap::with_capacity(2); + map.insert(TYPE_B1, TYPE_A1); + map.insert(TYPE_B2, TYPE_A2); + map + }); #[derive(PartialOrd, Hash, Eq, Ord, Debug, Default, Clone, PartialEq)] pub struct TypeA(pub ::pilota::FastStr); diff --git a/pilota-build/test_data/thrift/multi.rs b/pilota-build/test_data/thrift/multi.rs index 34aaeea2..cb8eeac4 100644 --- a/pilota-build/test_data/thrift/multi.rs +++ b/pilota-build/test_data/thrift/multi.rs @@ -956,7 +956,7 @@ pub mod multi { A { c: Some(super::default_value::C { off: Some(::pilota::FastStr::from_static_str("off")), - test_byte: Default::default(), + test_byte: None, }), } } @@ -989,7 +989,10 @@ pub mod multi { #[allow(unused_imports)] use ::pilota::{thrift::TLengthProtocolExt, Buf}; - let mut var_1 = None; + let mut var_1 = Some(super::default_value::C { + off: Some(::pilota::FastStr::from_static_str("off")), + test_byte: None, + }); let mut __pilota_decoding_field_id = None; @@ -1030,13 +1033,6 @@ pub mod multi { }; __protocol.read_struct_end()?; - if var_1.is_none() { - var_1 = Some(super::default_value::C { - off: Some(::pilota::FastStr::from_static_str("off")), - test_byte: Default::default(), - }); - } - let data = Self { c: var_1 }; ::std::result::Result::Ok(data) } @@ -1052,7 +1048,10 @@ pub mod multi { >, > { ::std::boxed::Box::pin(async move { - let mut var_1 = None; + let mut var_1 = Some(super::default_value::C { + off: Some(::pilota::FastStr::from_static_str("off")), + test_byte: None, + }); let mut __pilota_decoding_field_id = None; @@ -1093,13 +1092,6 @@ pub mod multi { }; __protocol.read_struct_end().await?; - if var_1.is_none() { - var_1 = Some(super::default_value::C { - off: Some(::pilota::FastStr::from_static_str("off")), - test_byte: Default::default(), - }); - } - let data = Self { c: var_1 }; ::std::result::Result::Ok(data) }) diff --git a/pilota-build/test_data/unknown_fields.rs b/pilota-build/test_data/unknown_fields.rs index beddca82..49c70526 100644 --- a/pilota-build/test_data/unknown_fields.rs +++ b/pilota-build/test_data/unknown_fields.rs @@ -1643,13 +1643,13 @@ pub mod unknown_fields { + __protocol.struct_end_len() } } - ::pilota::lazy_static::lazy_static! { - pub static ref TEST_MAP_LIST: ::pilota::AHashMap> = { + pub static TEST_MAP_LIST: ::std::sync::LazyLock< + ::pilota::AHashMap>, + > = ::std::sync::LazyLock::new(|| { let mut map = ::pilota::AHashMap::with_capacity(1); map.insert(1i32, ::std::vec!["hello"]); map - }; - } + }); #[derive( PartialOrd, Hash, @@ -3591,13 +3591,13 @@ pub mod unknown_fields { + __protocol.struct_end_len() } } - ::pilota::lazy_static::lazy_static! { - pub static ref TEST_MAP: ::pilota::AHashMap = { - let mut map = ::pilota::AHashMap::with_capacity(2); - map.insert(Index::A, "hello");map.insert(Index::B, "world"); - map - }; - } + pub static TEST_MAP: ::std::sync::LazyLock<::pilota::AHashMap> = + ::std::sync::LazyLock::new(|| { + let mut map = ::pilota::AHashMap::with_capacity(2); + map.insert(Index::A, "hello"); + map.insert(Index::B, "world"); + map + }); } pub mod void { diff --git a/pilota/src/thrift/mod.rs b/pilota/src/thrift/mod.rs index 3ea79638..b1f187b7 100644 --- a/pilota/src/thrift/mod.rs +++ b/pilota/src/thrift/mod.rs @@ -27,9 +27,7 @@ const ZERO_COPY_THRESHOLD: usize = 1024; // While 4KB is better for other platforms (mainly amd64 linux). const ZERO_COPY_THRESHOLD: usize = 4 * 1024; -lazy_static::lazy_static! { - pub static ref VOID_IDENT: TStructIdentifier = TStructIdentifier { name: "void" }; -} +pub static VOID_IDENT: TStructIdentifier = TStructIdentifier { name: "void" }; pub trait Message: Sized + Send { fn encode(&self, protocol: &mut T) -> Result<(), ThriftException>;