Skip to content

Commit bb772d8

Browse files
author
Foster Guo
committed
release: 0.15.2
1 parent bf5e02d commit bb772d8

11 files changed

Lines changed: 81 additions & 63 deletions

File tree

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,23 @@
11
# Changelog
22

33

4+
## 0.15.2 - 2026-04-11
5+
6+
### Changed
7+
8+
- **Python**: Batch methods (`batch_is_match`, `batch_process`, `batch_find_match`) use `PyBackedStr` for zero-copy string handling, avoiding redundant UTF-8 copies across the FFI boundary.
9+
- **Core**: Replace unsafe `get_unchecked` with safe indexing guarded by `assert_unchecked` hints across scan and pattern modules.
10+
- **Core**: Add safety assertions for bitset indexing in `DeleteMatcher`.
11+
- **Core**: Simplify text processing by inlining `replace_cow` functionality.
12+
- **Core**: Move `has_match` into `ScanState` and remove unused methods.
13+
- **Tooling**: Trim `cargo-all-features` allowlist to only the `perf` feature.
14+
15+
### Documentation
16+
17+
- Update all README Quick Start examples to use builder APIs (Python, Java, C) for consistency with Rust.
18+
- Remove phantom `process_iter` reference from Rust README (method was removed in 0.15.0).
19+
- Fix formatting in root README architecture diagram.
20+
421
## 0.15.1 - 2026-04-11
522

623
### Added

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ readme = "README.md"
1313
keywords = ["text", "string", "search", "pattern", "multi"]
1414
license = "Apache-2.0 OR MIT"
1515
repository = "https://github.com/Lips7/Matcher"
16-
version = "0.15.1"
16+
version = "0.15.2"
1717

1818
[profile.dev]
1919
split-debuginfo = "unpacked"

README.md

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,14 @@ pip install matcher_py
103103
```
104104

105105
```python
106-
import json
107-
from matcher_py import ProcessType, SimpleMatcher
108-
109-
matcher = SimpleMatcher(
110-
json.dumps({
111-
ProcessType.NONE: {
112-
1: "hello&world", # AND: both must appear
113-
2: "color|colour", # OR: either spelling
114-
3: r"\bcat\b", # word boundary
115-
}
116-
}).encode()
117-
)
106+
from matcher_py import ProcessType, SimpleMatcherBuilder
107+
108+
builder = SimpleMatcherBuilder()
109+
builder.add_word(ProcessType.NONE, 1, "hello&world") # AND: both must appear
110+
builder.add_word(ProcessType.NONE, 2, "color|colour") # OR: either spelling
111+
builder.add_word(ProcessType.NONE, 3, r"\bcat\b") # word boundary
112+
matcher = builder.build()
113+
118114
assert matcher.is_match("hello, world!")
119115
assert matcher.is_match("nice colour")
120116
assert not matcher.is_match("concatenate") # "cat" not a whole word
@@ -129,10 +125,14 @@ See the [Python README](./matcher_py/README.md) for full docs.
129125

130126
```java
131127
import com.matcherjava.SimpleMatcher;
132-
133-
// ProcessType.NONE = 1; word_id 1/2/3
134-
byte[] config = "{\"1\":{\"1\":\"hello&world\",\"2\":\"color|colour\",\"3\":\"\\\\bcat\\\\b\"}}".getBytes();
135-
try (SimpleMatcher matcher = new SimpleMatcher(config)) {
128+
import com.matcherjava.SimpleMatcherBuilder;
129+
import com.matcherjava.extensiontypes.ProcessType;
130+
131+
try (SimpleMatcher matcher = new SimpleMatcherBuilder()
132+
.add(ProcessType.NONE, 1, "hello&world") // AND: both must appear
133+
.add(ProcessType.NONE, 2, "color|colour") // OR: either spelling
134+
.add(ProcessType.NONE, 3, "\\bcat\\b") // word boundary
135+
.build()) {
136136
assert matcher.isMatch("hello, world!");
137137
assert matcher.isMatch("nice colour");
138138
assert !matcher.isMatch("concatenate"); // "cat" not a whole word
@@ -149,12 +149,16 @@ See the [Java README](./matcher_java/README.md) for full docs.
149149
```c
150150
#include "matcher_c.h"
151151

152-
// ProcessType NONE=1; word_ids 1, 2, 3
153-
void* m = init_simple_matcher("{\"1\":{\"1\":\"hello&world\",\"2\":\"color|colour\",\"3\":\"\\\\bcat\\\\b\"}}");
154-
simple_matcher_is_match(m, "hello, world!"); // true — AND
155-
simple_matcher_is_match(m, "nice colour"); // true — OR
156-
simple_matcher_is_match(m, "concatenate"); // false — word boundary
157-
drop_simple_matcher(m);
152+
void* builder = init_simple_matcher_builder();
153+
simple_matcher_builder_add_word(builder, PROCESS_TYPE_NONE, 1, "hello&world"); // AND
154+
simple_matcher_builder_add_word(builder, PROCESS_TYPE_NONE, 2, "color|colour"); // OR
155+
simple_matcher_builder_add_word(builder, PROCESS_TYPE_NONE, 3, "\\bcat\\b"); // word boundary
156+
void* matcher = simple_matcher_builder_build(builder);
157+
158+
simple_matcher_is_match(matcher, "hello, world!"); // true — AND
159+
simple_matcher_is_match(matcher, "nice colour"); // true — OR
160+
simple_matcher_is_match(matcher, "concatenate"); // false — word boundary
161+
drop_simple_matcher(matcher);
158162
```
159163
160164
See the [C README](./matcher_c/README.md) for full docs.

matcher_c/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,5 @@ name = "matcher_c"
1717
crate-type = ["cdylib", "rlib"]
1818

1919
[dependencies]
20-
matcher_rs = { path = "../matcher_rs", version = "0.15.1", features = ["serde", "rayon"] }
20+
matcher_rs = { path = "../matcher_rs", version = "0.15.2", features = ["serde", "rayon"] }
2121
sonic-rs = "0.5.8"

matcher_java/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,6 @@ crate-type = ["cdylib"]
1616
path = "src/main/rust/lib.rs"
1717

1818
[dependencies]
19-
matcher_rs = { path = "../matcher_rs", version = "0.15.1", features = ["serde", "rayon"] }
19+
matcher_rs = { path = "../matcher_rs", version = "0.15.2", features = ["serde", "rayon"] }
2020
jni = "0.22.4"
2121
sonic-rs = "0.5.8"

matcher_java/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ cp target/release/libmatcher_java.dylib matcher_java/src/main/resources/ # .so
3535
```xml
3636
<groupId>com.matcher_java</groupId>
3737
<artifactId>matcher_java</artifactId>
38-
<version>0.15.1</version>
38+
<version>0.15.2</version>
3939
```
4040

4141
## Usage

matcher_java/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
<groupId>com.matcher_java</groupId>
88
<artifactId>matcher_java</artifactId>
9-
<version>0.15.1</version>
9+
<version>0.15.2</version>
1010

1111
<name>matcher_java</name>
1212
<url>https://github.com/Lips7/Matcher</url>

matcher_py/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ name = "matcher_py"
1818
crate-type = ["cdylib"]
1919

2020
[dependencies]
21-
matcher_rs = { path = "../matcher_rs", version = "0.15.1", features = ["serde", "rayon"] }
21+
matcher_rs = { path = "../matcher_rs", version = "0.15.2", features = ["serde", "rayon"] }
2222
pyo3 = { version = "0.28.3", features = ["extension-module"] }
2323
sonic-rs = "0.5.8"
2424

matcher_py/README.md

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -75,16 +75,32 @@ print(reduce_text_process(ProcessType.DELETE_NORMALIZE, "hello, world!"))
7575
print(text_process(ProcessType.DELETE, "hello, world!"))
7676
```
7777

78-
### Simple Matcher Basic Usage
78+
### Simple Matcher — Builder (recommended)
7979

80-
Here’s an example of how to use the `SimpleMatcher`:
80+
```python
81+
from matcher_py import ProcessType, SimpleMatcherBuilder
82+
83+
builder = SimpleMatcherBuilder()
84+
builder.add_word(ProcessType.NONE, 1, "hello&world")
85+
builder.add_word(ProcessType.NONE, 2, "word&word~hello")
86+
builder.add_word(ProcessType.DELETE, 3, "hallo")
87+
matcher = builder.build()
88+
89+
assert matcher.is_match("hello^&!#*#&!^#*()world")
90+
result = matcher.process("hello,world,word,word,hallo")
91+
print(result)
92+
```
93+
94+
### Simple Matcher — JSON constructor
95+
96+
You can also construct from JSON bytes if you already have them:
8197

8298
```python
8399
import json
84100

85101
from matcher_py import ProcessType, SimpleMatcher
86102

87-
simple_matcher = SimpleMatcher(
103+
matcher = SimpleMatcher(
88104
json.dumps(
89105
{
90106
ProcessType.NONE: {
@@ -97,32 +113,20 @@ simple_matcher = SimpleMatcher(
97113
}
98114
).encode()
99115
)
100-
# Check if a text matches
101-
assert simple_matcher.is_match("hello^&!#*#&!^#*()world")
102-
# Perform simple processing
103-
result = simple_matcher.process("hello,world,word,word,hallo")
104-
print(result)
116+
assert matcher.is_match("hello^&!#*#&!^#*()world")
105117
```
106118

107119
### OR, NOT, and Word Boundary
108120

109121
```python
110-
import json
111-
112-
from matcher_py import ProcessType, SimpleMatcher
113-
114-
matcher = SimpleMatcher(
115-
json.dumps(
116-
{
117-
ProcessType.NONE: {
118-
1: "color|colour", # OR: matches either spelling
119-
2: "banana~peel", # NOT: "banana" without "peel"
120-
3: r"\bcat\b", # word boundary: whole word only
121-
4: r"bright&color|colour~\bdark\b", # combined
122-
}
123-
}
124-
).encode()
125-
)
122+
from matcher_py import ProcessType, SimpleMatcherBuilder
123+
124+
builder = SimpleMatcherBuilder()
125+
builder.add_word(ProcessType.NONE, 1, "color|colour") # OR
126+
builder.add_word(ProcessType.NONE, 2, "banana~peel") # NOT
127+
builder.add_word(ProcessType.NONE, 3, r"\bcat\b") # word boundary
128+
builder.add_word(ProcessType.NONE, 4, r"bright&color|colour~\bdark\b") # combined
129+
matcher = builder.build()
126130

127131
assert matcher.is_match("nice colour") # OR
128132
assert matcher.is_match("banana split") # NOT (no veto)

matcher_py/pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[project]
22
name = "matcher_py"
33
description = "A high-performance matcher designed to solve LOGICAL and TEXT VARIATIONS problems in word matching, implemented in Rust."
4-
version = "0.15.1"
4+
version = "0.15.2"
55
readme = "README.md"
66
requires-python = ">=3.8"
77
authors = [{ name = 'Foster Guo', email = "f975793771@gmail.com" }]

0 commit comments

Comments
 (0)