Skip to content

Commit

Permalink
Add UnmarshalString
Browse files Browse the repository at this point in the history
Before
'''
2512 B/op       83 allocs/op
'''

After
'''
2016 B/op         47 allocs/op
'''
  • Loading branch information
Sean-Der committed Mar 7, 2024
1 parent adf8269 commit 46f6da0
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 21 deletions.
8 changes: 4 additions & 4 deletions base_lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,12 @@ func (e syntaxError) Error() string {
}

type baseLexer struct {
value []byte
value string
pos int
}

func (l baseLexer) syntaxError() error {
return syntaxError{s: string(l.value), i: l.pos - 1}
return syntaxError{s: l.value, i: l.pos - 1}
}

func (l *baseLexer) unreadByte() error {
Expand Down Expand Up @@ -157,7 +157,7 @@ func (l *baseLexer) readField() (string, error) {
break
}
}
return string(l.value[start:stop]), nil
return l.value[start:stop], nil
}

// Returns symbols until line end
Expand All @@ -173,7 +173,7 @@ func (l *baseLexer) readLine() (string, error) {
trim++
}
if ch == '\n' {
return string(l.value[start : l.pos-trim]), nil
return l.value[start : l.pos-trim], nil
}
}
}
Expand Down
6 changes: 3 additions & 3 deletions base_lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ func TestLexer(t *testing.T) {
"with linebreak": "aaa \n",
"with linebreak 2": "aaa \r\n",
} {
l := &baseLexer{value: []byte(value)}
l := &baseLexer{value: value}
field, err := l.readField()
if err != nil {
t.Fatal(err)
Expand All @@ -28,7 +28,7 @@ func TestLexer(t *testing.T) {
})

t.Run("syntax error", func(t *testing.T) {
l := &baseLexer{value: []byte("12NaN")}
l := &baseLexer{value: "12NaN"}
_, err := l.readUint64Field()
if err != nil {
fmt.Println("error message:", err.Error())
Expand All @@ -38,7 +38,7 @@ func TestLexer(t *testing.T) {
})

t.Run("many fields", func(t *testing.T) {
l := &baseLexer{value: []byte("aaa 123\nf1 f2\nlast")}
l := &baseLexer{value: "aaa 123\nf1 f2\nlast"}

t.Run("first line", func(t *testing.T) {
field, err := l.readField()
Expand Down
8 changes: 4 additions & 4 deletions fuzz_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ package sdp
import "testing"

func FuzzUnmarshal(f *testing.F) {
f.Add([]byte{})
f.Add([]byte(CanonicalUnmarshalSDP))
f.Fuzz(func(t *testing.T, data []byte) {
f.Add("")
f.Add(CanonicalUnmarshalSDP)
f.Fuzz(func(t *testing.T, data string) {
// Check that unmarshalling any byte slice does not panic.
var sd SessionDescription
if err := sd.Unmarshal(data); err != nil {
if err := sd.UnmarshalString(data); err != nil {
return
}
// Check that we can marshal anything we unmarshalled.
Expand Down
2 changes: 1 addition & 1 deletion marshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ func TestMarshalCanonical(t *testing.T) {
func BenchmarkMarshal(b *testing.B) {
b.ReportAllocs()
var sd SessionDescription
err := sd.Unmarshal([]byte(CanonicalUnmarshalSDP))
err := sd.UnmarshalString(CanonicalUnmarshalSDP)
if err != nil {
b.Fatal(err)
}
Expand Down
10 changes: 8 additions & 2 deletions unmarshal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ var (
errSDPInvalidPortValue = errors.New("sdp: invalid port value")
)

// Unmarshal is the primary function that deserializes the session description
// UnmarshalString is the primary function that deserializes the session description
// message and stores it inside of a structured SessionDescription object.
//
// The States Transition Table describes the computation flow between functions
Expand Down Expand Up @@ -99,7 +99,7 @@ var (
// | s15 | | 14 | | | 15 | | | | 12 | | | | | | | | |
// | s16 | | 14 | | | | 15 | | | 12 | | | | | | | | |
// +--------+----+-------+----+-----+----+-----+---+----+----+---+---+-----+---+---+----+---+----+
func (s *SessionDescription) Unmarshal(value []byte) error {
func (s *SessionDescription) UnmarshalString(value string) error {
l := new(lexer)
l.desc = s
l.value = value
Expand All @@ -113,6 +113,12 @@ func (s *SessionDescription) Unmarshal(value []byte) error {
return nil
}

// Unmarshal converts the value into a []byte and then calls UnmarshalString.
// Callers should use the more performant UnmarshalString
func (s *SessionDescription) Unmarshal(value []byte) error {
return s.UnmarshalString(string(value))
}

func s1(l *lexer) (stateFn, error) {
return l.handleType(func(key byte) stateFn {
if key == 'v' {
Expand Down
13 changes: 6 additions & 7 deletions unmarshal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -303,7 +303,7 @@ func TestRoundTrip(t *testing.T) {
t.Run(test.Name, func(t *testing.T) {
sd := &SessionDescription{}

err := sd.Unmarshal([]byte(test.SDP))
err := sd.UnmarshalString(test.SDP)
if got, want := err, error(nil); !errors.Is(got, want) {
t.Fatalf("Unmarshal:\nerr=%v\nwant=%v", got, want)
}
Expand All @@ -327,7 +327,7 @@ func TestRoundTrip(t *testing.T) {

func TestUnmarshalRepeatTimes(t *testing.T) {
sd := &SessionDescription{}
if err := sd.Unmarshal([]byte(RepeatTimesSDP)); err != nil {
if err := sd.UnmarshalString(RepeatTimesSDP); err != nil {
t.Errorf("error: %v", err)
}

Expand All @@ -339,15 +339,15 @@ func TestUnmarshalRepeatTimes(t *testing.T) {
t.Errorf("error:\n\nEXPECTED:\n%v\nACTUAL:\n%v", RepeatTimesSDPExpected, string(actual))
}

err = sd.Unmarshal([]byte(TimingSDP + "r=\r\n"))
err = sd.UnmarshalString(TimingSDP + "r=\r\n")
if got, want := err, errSDPInvalidValue; !errors.Is(got, want) {
t.Fatalf("Marshal(): err=%v, want %v", got, want)
}
}

func TestUnmarshalTimeZones(t *testing.T) {
sd := &SessionDescription{}
if err := sd.Unmarshal([]byte(TimeZonesSDP)); err != nil {
if err := sd.UnmarshalString(TimeZonesSDP); err != nil {
t.Errorf("error: %v", err)
}

Expand All @@ -363,7 +363,7 @@ func TestUnmarshalTimeZones(t *testing.T) {
func TestUnmarshalNonNilAddress(t *testing.T) {
in := "v=0\r\no=0 0 0 IN IP4 0\r\ns=0\r\nc=IN IP4\r\nt=0 0\r\n"
var sd SessionDescription
err := sd.Unmarshal([]byte(in))
err := sd.UnmarshalString(in)
if err != nil {
t.Fatalf("failed to unmarshal %q", in)
}
Expand All @@ -378,10 +378,9 @@ func TestUnmarshalNonNilAddress(t *testing.T) {

func BenchmarkUnmarshal(b *testing.B) {
b.ReportAllocs()
raw := []byte(CanonicalUnmarshalSDP)
for i := 0; i < b.N; i++ {
var sd SessionDescription
err := sd.Unmarshal(raw)
err := sd.UnmarshalString(CanonicalUnmarshalSDP)
if err != nil {
b.Fatal(err)
}
Expand Down

0 comments on commit 46f6da0

Please sign in to comment.