-
Notifications
You must be signed in to change notification settings - Fork 6
/
frame.go
68 lines (57 loc) · 1.56 KB
/
frame.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package player
import (
"encoding/json"
"fmt"
)
// Frame represents asciinema-v2 frame.
// This is JSON-array with fixed size of 3 elements:
// [0]: frame delay in seconds (float64),
// [1]: frame type,
// [2]: frame data (escaped string).
type Frame struct {
// Time in seconds since record start.
Time float64
// Type of frame.
Type FrameType
// Data contains frame data.
Data []byte
}
// FrameUnmarshalError returned if frame conversion to struct failed.
type FrameUnmarshalError struct {
Description string
Index int
}
func (e *FrameUnmarshalError) Error() string {
return fmt.Sprintf("frame[%d]: %s", e.Index, e.Description)
}
// UnmarshalJSON implements json.Unmarshaler.
func (f *Frame) UnmarshalJSON(b []byte) error {
var rawFrame [3]interface{}
if err := json.Unmarshal(b, &rawFrame); err != nil {
return err
}
switch t := rawFrame[0].(type) {
case float64:
f.Time = t
default:
return &FrameUnmarshalError{Description: fmt.Sprintf("invalid type %T", t), Index: 0}
}
switch frameTypeRaw := rawFrame[1].(type) {
case string:
switch FrameType(frameTypeRaw) {
case InputFrame, OutputFrame:
f.Type = FrameType(frameTypeRaw)
default:
return &FrameUnmarshalError{Description: fmt.Sprintf("invalid value %v", frameTypeRaw), Index: 1}
}
default:
return &FrameUnmarshalError{Description: fmt.Sprintf("invalid type %T", frameTypeRaw), Index: 1}
}
switch text := rawFrame[2].(type) {
case string:
f.Data = []byte(text)
default:
return &FrameUnmarshalError{Description: fmt.Sprintf("invalid type %T", text), Index: 2}
}
return nil
}