Skip to content

Commit 142c33f

Browse files
authored
Merge pull request #773 from heygsc/feat/cow
use `cow-utils` instead
2 parents 0c5d668 + b676000 commit 142c33f

File tree

24 files changed

+77
-45
lines changed

24 files changed

+77
-45
lines changed

Cargo.lock

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

clippy.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
disallowed-methods = [
22
{ path = "str::to_ascii_lowercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_ascii_lowercase` instead." },
3+
{ path = "str::to_ascii_uppercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_ascii_uppercase` instead." },
4+
{ path = "str::to_lowercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_lowercase` instead." },
5+
{ path = "str::to_uppercase", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_to_uppercase` instead." },
6+
{ path = "str::replace", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_replace` instead." },
7+
{ path = "str::replacen", reason = "To avoid memory allocation, use `cow_utils::CowUtils::cow_replacen` instead." },
38
]

crates/gosub_config/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ log = "0.4.22"
1818
testing_logger = "0.1.1"
1919
url = "2.5.4"
2020
anyhow = "1.0.94"
21+
cow-utils = "0.1.3"
2122

2223
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
2324
rusqlite = "0.32.1"

crates/gosub_config/src/settings.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::errors::Error;
22
use core::fmt::Display;
3+
use cow_utils::CowUtils;
34
use log::warn;
45
use serde::{Deserialize, Deserializer, Serialize, Serializer};
56
use std::str::FromStr;
@@ -94,8 +95,8 @@ impl Setting {
9495
}
9596

9697
fn is_bool_value(s: &str) -> bool {
97-
let us = s.to_uppercase();
98-
if ["YES", "ON", "TRUE", "1"].contains(&us.as_str()) {
98+
let us = s.cow_to_uppercase();
99+
if ["YES", "ON", "TRUE", "1"].contains(&us.as_ref()) {
99100
return true;
100101
}
101102

crates/gosub_css3/src/matcher/styling.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use core::fmt::Debug;
2+
use cow_utils::CowUtils;
23
use itertools::Itertools;
34
use std::cmp::Ordering;
45
use std::collections::HashMap;
@@ -127,8 +128,8 @@ fn match_selector_part<'a, C: HasDocument>(
127128
let mut _got_buf = String::new();
128129
// If we need to match case-insensitive, just convert everything to lowercase for comparison
129130
if attr.case_insensitive {
130-
_wanted_buf = wanted_attr_name.to_lowercase();
131-
_got_buf = got_attr_value.to_lowercase();
131+
_wanted_buf = wanted_attr_name.cow_to_lowercase().to_string();
132+
_got_buf = got_attr_value.cow_to_lowercase().to_string();
132133

133134
wanted_attr_value = &_wanted_buf;
134135
got_attr_value = &_got_buf;

crates/gosub_css3/src/parser/at_rule.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::node::{Node, NodeType};
1313
use crate::parser::block::BlockParseMode;
1414
use crate::tokenizer::TokenType;
1515
use crate::Css3;
16+
use cow_utils::CowUtils;
1617
use gosub_shared::errors::{CssError, CssResult};
1718

1819
impl Css3<'_> {
@@ -59,7 +60,7 @@ impl Css3<'_> {
5960
log::trace!("parse_at_rule_prelude");
6061

6162
self.consume_whitespace_comments();
62-
let node = match name.to_lowercase().as_str() {
63+
let node = match name.cow_to_lowercase().as_ref() {
6364
"container" => Some(self.parse_at_rule_container_prelude()?),
6465
"font-face" => None,
6566
"import" => Some(self.parse_at_rule_import_prelude()?),
@@ -102,7 +103,7 @@ impl Css3<'_> {
102103
}
103104

104105
// parse block. They may or may not have nested rules depending on the is_declaration and block type
105-
let node = match name.to_lowercase().as_str() {
106+
let node = match name.cow_to_lowercase().as_ref() {
106107
"container" => Some(self.parse_block(mode)?),
107108
"font-face" => Some(self.parse_block(BlockParseMode::StyleBlock)?),
108109
"import" => None,

crates/gosub_css3/src/parser/at_rule/media.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::node::{FeatureKind, Node, NodeType};
22
use crate::tokenizer::TokenType;
33
use crate::Css3;
4+
use cow_utils::CowUtils;
45
use gosub_shared::errors::{CssError, CssResult};
56

67
impl Css3<'_> {
@@ -15,13 +16,13 @@ impl Css3<'_> {
1516
TokenType::Number(value) => Ok(Node::new(NodeType::Number { value }, loc)),
1617
TokenType::Dimension { value, unit } => Ok(Node::new(NodeType::Dimension { value, unit }, loc)),
1718
TokenType::Function(name) => {
18-
let name = name.to_lowercase();
19-
let args = self.parse_pseudo_function(name.as_str())?;
19+
let name = name.cow_to_lowercase();
20+
let args = self.parse_pseudo_function(name.as_ref())?;
2021
self.consume(TokenType::RParen)?;
2122

2223
Ok(Node::new(
2324
NodeType::Function {
24-
name,
25+
name: name.to_string(),
2526
arguments: vec![args],
2627
},
2728
loc,
@@ -111,13 +112,13 @@ impl Css3<'_> {
111112
}
112113
TokenType::Ident(value) => Some(Node::new(NodeType::Ident { value }, t.location)),
113114
TokenType::Function(name) => {
114-
let name = name.to_lowercase();
115-
let args = self.parse_pseudo_function(name.as_str())?;
115+
let name = name.cow_to_lowercase();
116+
let args = self.parse_pseudo_function(name.as_ref())?;
116117
self.consume(TokenType::RParen)?;
117118

118119
Some(Node::new(
119120
NodeType::Function {
120-
name,
121+
name: name.to_string(),
121122
arguments: vec![args],
122123
},
123124
t.location,
@@ -208,8 +209,8 @@ impl Css3<'_> {
208209
_ => unreachable!(),
209210
};
210211

211-
let s = ident.to_lowercase();
212-
media_type = if ["not", "only"].contains(&s.as_str()) {
212+
let s = ident.cow_to_lowercase();
213+
media_type = if ["not", "only"].contains(&s.as_ref()) {
213214
self.consume_whitespace_comments();
214215
modifier = ident;
215216
self.consume_any_ident()?

crates/gosub_css3/src/parser/selector.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::node::{Node, NodeType};
22
use crate::tokenizer::TokenType;
33
use crate::Css3;
4+
use cow_utils::CowUtils;
45
use gosub_shared::errors::CssError;
56
use gosub_shared::errors::CssResult;
67

@@ -222,13 +223,13 @@ impl Css3<'_> {
222223
let value = match t.token_type {
223224
TokenType::Ident(value) => Node::new(NodeType::Ident { value }, t.location),
224225
TokenType::Function(name) => {
225-
let name = name.to_lowercase();
226-
let args = self.parse_pseudo_function(name.as_str())?;
226+
let name = name.cow_to_lowercase();
227+
let args = self.parse_pseudo_function(name.as_ref())?;
227228
self.consume(TokenType::RParen)?;
228229

229230
Node::new(
230231
NodeType::Function {
231-
name,
232+
name: name.to_string(),
232233
arguments: vec![args],
233234
},
234235
t.location,

crates/gosub_html5/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ regex = "1"
2222
serde = { version = "1.0", features = ["derive"] }
2323
serde_json = { version = "1.0", features = ["preserve_order"] }
2424
serde_derive = "1.0"
25+
cow-utils = "0.1.3"
2526

2627
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
2728
ureq = "2.12.1"

crates/gosub_html5/src/parser.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::parser::errors::{ErrorLogger, ParserError};
1313
use crate::tokenizer::state::State;
1414
use crate::tokenizer::token::Token;
1515
use crate::tokenizer::{ParserData, Tokenizer, CHAR_REPLACEMENT};
16+
use cow_utils::CowUtils;
1617
use gosub_interface::config::HasDocument;
1718
use gosub_interface::css3::{CssOrigin, CssSystem};
1819
use gosub_interface::document::{Document, DocumentFragment, DocumentType};
@@ -595,7 +596,7 @@ impl<'a, C: HasDocument> Html5Parser<'a, C> {
595596
let mut node_idx = self.open_elements.len() - 1;
596597
let mut node = get_node_by_id!(self.document, self.open_elements[node_idx]);
597598

598-
if get_element_data!(node).name().to_lowercase() != *name {
599+
if get_element_data!(node).name().cow_to_lowercase() != *name {
599600
self.parse_error("end tag does not match current node");
600601
}
601602

@@ -607,7 +608,7 @@ impl<'a, C: HasDocument> Html5Parser<'a, C> {
607608
_ => {}
608609
}
609610

610-
if get_element_data!(node).name().to_lowercase() == *name {
611+
if get_element_data!(node).name().cow_to_lowercase() == *name {
611612
while let Some(node_id) = self.open_elements.pop() {
612613
if node_id == node.id() {
613614
break;
@@ -2771,7 +2772,7 @@ impl<'a, C: HasDocument> Html5Parser<'a, C> {
27712772

27722773
self.acknowledge_closing_tag(*is_self_closing);
27732774

2774-
if !attributes.contains_key("type") || attributes.get("type").unwrap().to_lowercase() != *"hidden" {
2775+
if !attributes.contains_key("type") || attributes.get("type").unwrap().cow_to_lowercase() != *"hidden" {
27752776
self.frameset_ok = false;
27762777
}
27772778
}
@@ -3329,7 +3330,7 @@ impl<'a, C: HasDocument> Html5Parser<'a, C> {
33293330
attributes,
33303331
..
33313332
} if name == "input" => {
3332-
if !attributes.contains_key("type") || attributes.get("type").unwrap().to_lowercase() != *"hidden" {
3333+
if !attributes.contains_key("type") || attributes.get("type").unwrap().cow_to_lowercase() != *"hidden" {
33333334
anything_else = true;
33343335
} else {
33353336
self.parse_error("input tag not allowed in in table insertion mode");

crates/gosub_html5/src/parser/quirks.rs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::parser::Html5Parser;
2+
use cow_utils::CowUtils;
23
use gosub_interface::config::HasDocument;
34
use gosub_interface::node::QuirksMode;
45

@@ -16,47 +17,47 @@ impl<C: HasDocument> Html5Parser<'_, C> {
1617
}
1718

1819
if let Some(value) = pub_identifier {
19-
let pub_id = value.to_lowercase();
20-
if QUIRKS_PUB_IDENTIFIER_EQ.contains(&pub_id.as_str()) {
20+
let pub_id = value.cow_to_lowercase();
21+
if QUIRKS_PUB_IDENTIFIER_EQ.contains(&pub_id.as_ref()) {
2122
return QuirksMode::Quirks;
2223
}
2324

2425
if QUIRKS_PUB_IDENTIFIER_PREFIX
2526
.iter()
26-
.any(|&prefix| pub_id.as_str().starts_with(prefix))
27+
.any(|&prefix| pub_id.as_ref().starts_with(prefix))
2728
{
2829
return QuirksMode::Quirks;
2930
}
3031

3132
if sys_identifier.is_some()
3233
&& LIMITED_QUIRKS_PUB_IDENTIFIER_PREFIX_NOT_MISSING_SYS
3334
.iter()
34-
.any(|&prefix| pub_id.as_str().starts_with(prefix))
35+
.any(|&prefix| pub_id.as_ref().starts_with(prefix))
3536
{
3637
return QuirksMode::LimitedQuirks;
3738
}
3839

3940
if sys_identifier.is_none()
4041
&& QUIRKS_PUB_IDENTIFIER_PREFIX_MISSING_SYS
4142
.iter()
42-
.any(|&prefix| pub_id.as_str().starts_with(prefix))
43+
.any(|&prefix| pub_id.as_ref().starts_with(prefix))
4344
{
4445
return QuirksMode::Quirks;
4546
}
4647

4748
if LIMITED_QUIRKS_PUB_IDENTIFIER_PREFIX
4849
.iter()
49-
.any(|&prefix| pub_id.as_str().starts_with(prefix))
50+
.any(|&prefix| pub_id.as_ref().starts_with(prefix))
5051
{
5152
return QuirksMode::LimitedQuirks;
5253
}
5354
}
5455

5556
if let Some(value) = sys_identifier {
56-
let sys_id = value.to_lowercase();
57+
let sys_id = value.cow_to_lowercase();
5758
if QUIRKS_SYS_IDENTIFIER_EQ
5859
.iter()
59-
.any(|&prefix| sys_id.as_str().starts_with(prefix))
60+
.any(|&prefix| sys_id.as_ref().starts_with(prefix))
6061
{
6162
return QuirksMode::Quirks;
6263
}

crates/gosub_html5/src/testing/tree_construction/fixture.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::testing::tree_construction::parser::{parse_fixture, QUOTED_DOUBLE_NEWLINE};
22
use crate::testing::tree_construction::Test;
33
use crate::testing::{FIXTURE_ROOT, TREE_CONSTRUCTION_PATH};
4+
use cow_utils::CowUtils;
45
use gosub_shared::types::Result;
56
use std::fs;
67
use std::path::{Path, PathBuf};
@@ -77,7 +78,7 @@ pub fn read_fixtures(filenames: Option<&[&str]>) -> Result<Vec<FixtureFile>> {
7778
// have a "|" prefix using an "\n" delimiter. Otherwise strip "\n" from lines.
7879
fn create_document_array(s: &str) -> Vec<String> {
7980
let document = s
80-
.replace(QUOTED_DOUBLE_NEWLINE, "\"\n\n\"")
81+
.cow_replace(QUOTED_DOUBLE_NEWLINE, "\"\n\n\"")
8182
.split('|')
8283
.skip(1)
8384
.flat_map(|l| (!l.is_empty()).then(|| format!("|{}", l.trim_end())))

crates/gosub_html5/src/testing/tree_construction/parser.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
// See https://github.com/html5lib/html5lib-tests/tree/master/tree-construction
2+
use cow_utils::CowUtils;
23
use gosub_shared::types::{Error, Result};
34
use nom::{
45
branch::alt,
@@ -302,7 +303,7 @@ fn trim_last_newline(s: String) -> String {
302303

303304
pub fn parse_fixture(i: &str) -> Result<Vec<TestSpec>> {
304305
// Deal with a corner case that makes it hard to parse tricky01.dat.
305-
let input = i.replace("\"\n\n\"", QUOTED_DOUBLE_NEWLINE).clone() + "\n";
306+
let input = i.cow_replace("\"\n\n\"", QUOTED_DOUBLE_NEWLINE).clone() + "\n";
306307

307308
let files = map(
308309
tuple((separated_list1(tag("\n\n"), test), multispace0)),

crates/gosub_html5/src/tokenizer.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::node::HTML_NAMESPACE;
1212
use crate::parser::errors::{ErrorLogger, ParserError};
1313
use crate::tokenizer::state::State;
1414
use crate::tokenizer::token::Token;
15+
use cow_utils::CowUtils;
1516
use gosub_shared::byte_stream::Character::{Ch, StreamEnd};
1617
use gosub_shared::byte_stream::{ByteStream, Character, Location, LocationHandler, Stream};
1718
use gosub_shared::types::Result;
@@ -1235,7 +1236,7 @@ impl<'stream> Tokenizer<'stream> {
12351236
continue;
12361237
}
12371238

1238-
if Character::slice_to_string(self.stream.get_slice(7)).to_uppercase() == "DOCTYPE" {
1239+
if Character::slice_to_string(self.stream.get_slice(7)).cow_to_uppercase() == "DOCTYPE" {
12391240
self.stream_next_n(7);
12401241
self.state = State::DOCTYPE;
12411242
continue;
@@ -1605,12 +1606,12 @@ impl<'stream> Tokenizer<'stream> {
16051606
}
16061607
_ => {
16071608
self.stream_prev();
1608-
if Character::slice_to_string(self.stream.get_slice(6)).to_uppercase() == "PUBLIC" {
1609+
if Character::slice_to_string(self.stream.get_slice(6)).cow_to_uppercase() == "PUBLIC" {
16091610
self.stream_next_n(6);
16101611
self.state = State::AfterDOCTYPEPublicKeyword;
16111612
continue;
16121613
}
1613-
if Character::slice_to_string(self.stream.get_slice(6)).to_uppercase() == "SYSTEM" {
1614+
if Character::slice_to_string(self.stream.get_slice(6)).cow_to_uppercase() == "SYSTEM" {
16141615
self.stream_next_n(6);
16151616
self.state = State::AfterDOCTYPESystemKeyword;
16161617
continue;

crates/gosub_jsapi/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ description = "Web Javascript API"
1010
gosub_shared = { version = "0.1.1", registry = "gosub", path = "../gosub_shared", features = [] }
1111
uuid = { version = "1.11.0", features = ["v4"] }
1212
regex = "1"
13+
cow-utils = "0.1.3"

0 commit comments

Comments
 (0)