Skip to content

Commit 503d0e2

Browse files
authored
Merge pull request #36 from b-per/field-as-int
Allow setting struct fields as int
2 parents 6b949f5 + 32b1002 commit 503d0e2

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,19 @@ func main() {
118118
}
119119
```
120120

121+
### Ints
122+
123+
It is also possible to set struct fields as `int` to get the string automatically converted.
124+
125+
```go
126+
// Matches "12 wombats", "1 wombat" and store the number as int
127+
type Wisdom struct {
128+
Number int `^\d+`
129+
_ string `\s+`
130+
Animal string `\w+`
131+
}
132+
```
133+
121134
### Optional fields
122135

123136
When nesting one struct within another, you can make the nested struct optional by marking it with `?`. The following example parses floating point numbers with optional sign and exponent:

builder.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const (
1616
PosRole
1717
SubstructRole
1818
StringScalarRole
19+
IntScalarRole
1920
ByteSliceScalarRole
2021
SubmatchScalarRole
2122
)
@@ -106,6 +107,8 @@ func (b *builder) terminal(f reflect.StructField, fullName string) (*Field, *syn
106107
role = EmptyRole
107108
case stringType:
108109
role = StringScalarRole
110+
case intType:
111+
role = IntScalarRole
109112
case byteSliceType:
110113
role = ByteSliceScalarRole
111114
case submatchType:

inflate.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,21 @@ package restructure
33
import (
44
"fmt"
55
"reflect"
6+
"strconv"
67
)
78

89
var (
910
posType = reflect.TypeOf(Pos(0))
1011

1112
emptyType = reflect.TypeOf(struct{}{})
1213
stringType = reflect.TypeOf("")
14+
intType = reflect.TypeOf(1)
1315
byteSliceType = reflect.TypeOf([]byte{})
1416
submatchType = reflect.TypeOf(Submatch{})
1517
scalarTypes = []reflect.Type{
1618
emptyType,
1719
stringType,
20+
intType,
1821
byteSliceType,
1922
submatchType,
2023
}
@@ -77,6 +80,13 @@ func inflateScalar(dest reflect.Value, match *match, captureIndex int, role Role
7780
case StringScalarRole:
7881
dest.SetString(string(buf))
7982
return nil
83+
case IntScalarRole:
84+
if intVal, err := strconv.Atoi(string(buf)); err != nil {
85+
return fmt.Errorf("unable to capture into %s", dest.Type().String())
86+
} else {
87+
dest.SetInt(int64(intVal))
88+
return nil
89+
}
8090
case ByteSliceScalarRole:
8191
dest.SetBytes(buf)
8292
return nil
@@ -128,7 +138,7 @@ func inflateStruct(dest reflect.Value, match *match, structure *Struct) error {
128138
if err := inflatePos(val, match, field.capture); err != nil {
129139
return err
130140
}
131-
case StringScalarRole, ByteSliceScalarRole, SubmatchScalarRole:
141+
case StringScalarRole, ByteSliceScalarRole, SubmatchScalarRole, IntScalarRole:
132142
val := dest.FieldByIndex(field.index)
133143
if err := inflateScalar(val, match, field.capture, field.role); err != nil {
134144
return err

restructure_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,3 +308,19 @@ func TestFindAllWords_Regions(t *testing.T) {
308308
assertRegion(t, "is", 4, 6, words[1].S)
309309
assertRegion(t, "spam", 7, 11, words[2].S)
310310
}
311+
312+
type ExprWithInt struct {
313+
Number int `regexp:"^\\d+"`
314+
_ string `regexp:"\\s+"`
315+
Animal string `regexp:"\\w+$"`
316+
}
317+
318+
func TestMatchWithInt(t *testing.T) {
319+
pattern, err := Compile(ExprWithInt{}, Options{})
320+
require.NoError(t, err)
321+
322+
var v ExprWithInt
323+
assert.True(t, pattern.Find(&v, "4 wombats"))
324+
assert.Equal(t, 4, v.Number)
325+
assert.Equal(t, "wombats", v.Animal)
326+
}

0 commit comments

Comments
 (0)