commit 598fdad5e83b6942731dd84ef231c3f8e605e5fe
parent 52ca0d40aee46b2fdb156b73c5c16509f3e3505e
Author: Oliver Lowe <o@olowe.co>
Date: Wed, 22 May 2024 13:52:32 +1000
m3u8: correctly parse resolution and byte range
The lexer wasn't emitting the expected tokens to our parser. Now we
handle the cases where numbers are split by "x" and "@" as in
resolutions and byte range strings.
Diffstat:
2 files changed, 19 insertions(+), 11 deletions(-)
diff --git a/m3u8/lex.go b/m3u8/lex.go
@@ -232,9 +232,6 @@ func lexAttrValue(l *lexer) stateFn {
return lexNumber(l)
case '"':
return lexQString(l)
- case '@':
- // we're lexing a byte range, e.g. 69@420
- return lexRawString(l)
}
if isTagNameChar(r) {
return lexRawString(l)
@@ -245,6 +242,10 @@ func lexAttrValue(l *lexer) stateFn {
func lexNumber(l *lexer) stateFn {
for {
switch r := l.peek(); r {
+ case 'x', '@':
+ // are we lexing a resolution? e.g. 640x480
+ // or a byte range? e.g. 69@3000
+ return lexRawString(l)
case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.':
l.next()
continue
@@ -269,7 +270,7 @@ func lexQString(l *lexer) stateFn {
func lexRawString(l *lexer) stateFn {
for {
- if !isTagNameChar(l.peek()) {
+ if l.peek() == ',' || l.peek() == '\n' {
break
}
l.next()
diff --git a/m3u8/parse_test.go b/m3u8/parse_test.go
@@ -1,23 +1,30 @@
package m3u8
import (
- "fmt"
"os"
+ "path"
+ "path/filepath"
"testing"
"time"
)
func TestParse(t *testing.T) {
- f, err := os.Open("testdata/bbb.m3u8")
+ names, err := filepath.Glob("testdata/*.m3u8")
if err != nil {
t.Fatal(err)
}
- defer f.Close()
- p, err := ParsePlaylist(f)
- if err != nil {
- t.Fatal(err)
+ for _, name := range names {
+ t.Run(path.Base(name), func(t *testing.T) {
+ f, err := os.Open(name)
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer f.Close()
+ if _, err := ParsePlaylist(f); err != nil {
+ t.Fatal(err)
+ }
+ })
}
- fmt.Println(p.Segments[0])
}
func TestParseDuration(t *testing.T) {