Skip to content

Commit 05e6ac2

Browse files
authored
Support JSON Marshal/Unmarshal (#77)
Support JSON Marshal/Unmarshal
1 parent 03d34d8 commit 05e6ac2

File tree

2 files changed

+60
-3
lines changed

2 files changed

+60
-3
lines changed

regexp.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,12 @@ import (
1818
"github.com/dlclark/regexp2/syntax"
1919
)
2020

21-
// Default timeout used when running regexp matches -- "forever"
22-
var DefaultMatchTimeout = time.Duration(math.MaxInt64)
21+
var (
22+
// DefaultMatchTimeout used when running regexp matches -- "forever"
23+
DefaultMatchTimeout = time.Duration(math.MaxInt64)
24+
// DefaultUnmarshalOptions used when unmarshaling a regex from text
25+
DefaultUnmarshalOptions = None
26+
)
2327

2428
// Regexp is the representation of a compiled regular expression.
2529
// A Regexp is safe for concurrent use by multiple goroutines.
@@ -43,7 +47,7 @@ type Regexp struct {
4347
code *syntax.Code // compiled program
4448

4549
// cache of machines for running regexp
46-
muRun sync.Mutex
50+
muRun *sync.Mutex
4751
runner []*runner
4852
}
4953

@@ -72,6 +76,7 @@ func Compile(expr string, opt RegexOptions) (*Regexp, error) {
7276
capsize: code.Capsize,
7377
code: code,
7478
MatchTimeout: DefaultMatchTimeout,
79+
muRun: &sync.Mutex{},
7580
}, nil
7681
}
7782

@@ -371,3 +376,20 @@ func (re *Regexp) GroupNumberFromName(name string) int {
371376

372377
return -1
373378
}
379+
380+
// MarshalText implements [encoding.TextMarshaler]. The output
381+
// matches that of calling the [Regexp.String] method.
382+
func (re *Regexp) MarshalText() ([]byte, error) {
383+
return []byte(re.String()), nil
384+
}
385+
386+
// UnmarshalText implements [encoding.TextUnmarshaler] by calling
387+
// [Compile] on the encoded value.
388+
func (re *Regexp) UnmarshalText(text []byte) error {
389+
newRE, err := Compile(string(text), DefaultUnmarshalOptions)
390+
if err != nil {
391+
return err
392+
}
393+
*re = *newRE
394+
return nil
395+
}

regexp_test.go

+35
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package regexp2
22

33
import (
4+
"encoding/json"
45
"fmt"
56
"reflect"
67
"strings"
@@ -1329,3 +1330,37 @@ func TestParseShortSlashPEnd(t *testing.T) {
13291330
t.Fatalf("Expected match")
13301331
}
13311332
}
1333+
1334+
func TestMarshal(t *testing.T) {
1335+
re := MustCompile(`.*`, 0)
1336+
m, err := json.Marshal(re)
1337+
if err != nil {
1338+
t.Fatalf("Unexpected error: %v", err)
1339+
}
1340+
if string(m) != `".*"` {
1341+
t.Fatalf(`Expected ".*"`)
1342+
}
1343+
}
1344+
1345+
func TestUnMarshal(t *testing.T) {
1346+
DefaultUnmarshalOptions = IgnoreCase
1347+
bytes := []byte(`"^[abc]"`)
1348+
var re *Regexp
1349+
err := json.Unmarshal(bytes, &re)
1350+
if err != nil {
1351+
t.Fatalf("Unexpected error: %v", err)
1352+
}
1353+
if re.options != IgnoreCase {
1354+
t.Fatalf("Expected options ignore case")
1355+
}
1356+
if re.String() != `^[abc]` {
1357+
t.Fatalf(`Expected "^[abc]"`)
1358+
}
1359+
ok, err := re.MatchString("A")
1360+
if err != nil {
1361+
t.Fatalf("Unexpected error: %v", err)
1362+
}
1363+
if !ok {
1364+
t.Fatalf(`Expected match`)
1365+
}
1366+
}

0 commit comments

Comments
 (0)