From 2499f76df13cc8b57617ba3054823920d9c3803e Mon Sep 17 00:00:00 2001 From: Don Isaac Date: Wed, 28 Aug 2024 19:55:45 -0400 Subject: [PATCH] perf(extract): use `SyncString` instead of `String` (#71) --- src/extract/collector.rs | 8 +++-- src/extract/error.rs | 6 ++-- src/extract/mod.rs | 1 + src/extract/util.rs | 72 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 81 insertions(+), 6 deletions(-) create mode 100644 src/extract/util.rs diff --git a/src/extract/collector.rs b/src/extract/collector.rs index 9e0c9a5..38fa24a 100644 --- a/src/extract/collector.rs +++ b/src/extract/collector.rs @@ -32,7 +32,7 @@ use crate::{ http::random_ua, walk::Script, ApiKeyExtractor, Config, ScriptMessage, ScriptReceiver, }; -use super::{error::DownloadScriptDiagnostic, ApiKeyError}; +use super::{error::DownloadScriptDiagnostic, util::SyncString, ApiKeyError}; #[derive(Debug)] pub enum ApiKeyMessage { @@ -249,14 +249,16 @@ impl ApiKeyCollector { // convert into an ApiKeyError and send over channel if !api_keys.is_empty() { let num_keys = api_keys.len(); - let url_string = url.to_string(); + let url_string = SyncString::from(url.to_string()); let source = Arc::new( NamedSource::new(url_string.clone(), script.to_string()) .with_language("javascript"), ); let api_keys = api_keys .into_iter() - .map(|api_key| ApiKeyError::new(api_key, url_string.clone(), &source, &self.config)) + .map(|api_key| { + ApiKeyError::new(api_key, url_string.clone().into(), &source, &self.config) + }) .collect::>(); self.sender .send(ApiKeyMessage::Keys(api_keys)) diff --git a/src/extract/error.rs b/src/extract/error.rs index 0fcdef6..f310167 100644 --- a/src/extract/error.rs +++ b/src/extract/error.rs @@ -40,13 +40,13 @@ pub struct ApiKeyError { pub rule_id: String, pub secret: String, pub key_name: Option, - pub url: String, + pub url: Arc, } impl ApiKeyError { pub fn new( api_key: ApiKey<'_>, - url: String, + url: Arc, source: &Arc>, config: &Config, ) -> Self { @@ -101,7 +101,7 @@ impl Serialize for ApiKeyError { key.serialize_field("secret", &self.secret)?; key.serialize_field("line", &line)?; key.serialize_field("column", &column)?; - key.serialize_field("script_url", &self.url)?; + key.serialize_field("script_url", self.url.as_ref())?; key.end() } diff --git a/src/extract/mod.rs b/src/extract/mod.rs index e3977d4..1b0933a 100644 --- a/src/extract/mod.rs +++ b/src/extract/mod.rs @@ -1,6 +1,7 @@ mod collector; mod error; mod extractor; +mod util; mod visit; pub use collector::{ApiKeyCollector, ApiKeyMessage, ApiKeyReceiver, ApiKeySender}; diff --git a/src/extract/util.rs b/src/extract/util.rs new file mode 100644 index 0000000..cf16e72 --- /dev/null +++ b/src/extract/util.rs @@ -0,0 +1,72 @@ +use std::{borrow::Borrow, ops::Deref, sync::Arc}; + +/// Nominal type for [`Arc`]. +/// +/// Needed because [`Arc`] doesn't implement [`AsRef`] +#[derive(Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] +pub struct SyncString(Arc); + +impl Deref for SyncString { + type Target = String; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl From for Arc { + fn from(s: SyncString) -> Self { + s.0 + } +} + +impl From for SyncString { + fn from(s: String) -> Self { + Self(Arc::new(s)) + } +} + +impl Clone for SyncString { + fn clone(&self) -> Self { + Self(Arc::clone(&self.0)) + } +} + +impl AsRef for SyncString { + fn as_ref(&self) -> &String { + &self.0 + } +} + +impl AsRef for SyncString { + fn as_ref(&self) -> &str { + &self.0 + } +} + +impl Borrow for SyncString { + fn borrow(&self) -> &str { + &self.0 + } +} + +impl Borrow for SyncString { + fn borrow(&self) -> &String { + &self.0 + } +} + +impl PartialEq for SyncString { + fn eq(&self, other: &str) -> bool { + self.0.as_ref() == other + } +} + +impl serde::Serialize for SyncString { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + self.0.serialize(serializer) + } +}