Commit Diff


commit - 093b7480bc7275b0047361f2f87d3992bc71e5ee
commit + a5e36fbfb60aadd58d7a06c29272251c0a8f8c0e
blob - 3789c873abda6c7313d8e49d44f5bce71970f434
blob + f20f8a3d8585da03597a22dc361b29eebb0727f2
--- m3u8/segment.go
+++ m3u8/segment.go
@@ -28,59 +28,43 @@ const (
 // parseSegment returns the next segment from items and the leading
 // item which indicated the start of a segment.
 func parseSegment(items chan item, leading item) (*Segment, error) {
+	// we've already read one item, so send everything through again
+	// starting with the leading item to maintain the lexer's original order.
+	segItems := make(chan item)
+	go func() {
+		segItems <- leading
+		for it := range items {
+			if it.typ == itemURL {
+				segItems <- it
+				close(segItems)
+				return
+			}
+			segItems <- it
+		}
+	}()
+
 	var seg Segment
-	switch leading.typ {
-	case itemTag:
-		switch leading.val {
-		case tagSegmentDuration:
-			it := <-items
-			dur, err := parseSegmentDuration(it)
-			if err != nil {
-				return nil, fmt.Errorf("parse segment duration: %w", err)
-			}
-			seg.Duration = dur
-		case tagKey:
-			key, err := parseKey(items)
-			if err != nil {
-				return nil, fmt.Errorf("parse key: %w", err)
-			}
-			seg.Key = &key
-		case tagMap:
-			m, err := parseMap(items)
-			if err != nil {
-				return nil, fmt.Errorf("parse map: %w", err)
-			}
-			seg.Map = &m
-		default:
-			return nil, fmt.Errorf("parse leading item %s: unsupported", leading)
-		}
-	}
-
-	for it := range items {
+	for it := range segItems {
 		switch it.typ {
+		case itemNewline:
+			continue
 		case itemError:
 			return nil, errors.New(it.val)
 		case itemURL:
 			seg.URI = it.val
 			return &seg, nil
-		case itemNewline:
-			continue
-		default:
-			if it.typ != itemTag {
-				return nil, fmt.Errorf("unexpected %s", it)
-			}
 		}
 
 		switch it.val {
 		case tagSegmentDuration:
-			it = <-items
+			it = <-segItems
 			dur, err := parseSegmentDuration(it)
 			if err != nil {
 				return nil, fmt.Errorf("parse segment duration: %w", err)
 			}
 			seg.Duration = dur
 		case tagByteRange:
-			it = <-items
+			it = <-segItems
 			r, err := parseByteRange(it.val)
 			if err != nil {
 				return nil, fmt.Errorf("parse byte range: %w", err)
@@ -89,19 +73,19 @@ func parseSegment(items chan item, leading item) (*Seg
 		case tagDiscontinuity:
 			seg.Discontinuity = true
 		case tagKey:
-			key, err := parseKey(items)
+			key, err := parseKey(segItems)
 			if err != nil {
 				return nil, fmt.Errorf("parse key: %w", err)
 			}
 			seg.Key = &key
 		case tagMap:
-			m, err := parseMap(items)
+			m, err := parseMap(segItems)
 			if err != nil {
 				return nil, fmt.Errorf("parse map: %w", err)
 			}
 			seg.Map = &m
 		case tagDateTime:
-			it = <-items
+			it = <-segItems
 			t, err := time.Parse(time.RFC3339Nano, it.val)
 			if err != nil {
 				return nil, fmt.Errorf("bad date time tag: %w", err)