diff options
Diffstat (limited to 'demux.go')
-rw-r--r-- | demux.go | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/demux.go b/demux.go new file mode 100644 index 0000000..632630d --- /dev/null +++ b/demux.go @@ -0,0 +1,75 @@ +package binproto + +type urReturn struct { + ut UnitType + data interface{} +} + +type Demux struct { + ur UnitReader + events, other chan urReturn + err error +} + +func NewDemux(ur UnitReader) (d *Demux) { + d = &Demux{ + ur: ur, + events: make(chan urReturn), + other: make(chan urReturn), + err: nil} + go d.demux() + return +} + +func (d *Demux) demux() { + inEvent := false + nesting := 0 + + for { + ut, data, err := d.ur.ReadUnit() + if err != nil { + d.err = err + close(d.events) + close(d.other) + return + } + + if inEvent { + switch ut { + case UTList, UTIdKVMap, UTTextKVMap: + nesting++ + case UTTerm: + nesting-- + } + + d.events <- urReturn{ut, data} + + if nesting <= 0 { + inEvent = false + } + } else if ut == UTEvent { + d.events <- urReturn{ut, data} + inEvent = true + nesting = 0 + } else { + d.other <- urReturn{ut, data} + } + } +} + +type PartUnitReader struct { + ch chan urReturn + d *Demux +} + +func (d *Demux) Events() *PartUnitReader { return &PartUnitReader{d.events, d} } +func (d *Demux) Other() *PartUnitReader { return &PartUnitReader{d.other, d} } + +func (pur *PartUnitReader) ReadUnit() (UnitType, interface{}, error) { + urr, ok := <-pur.ch + if !ok { + return 0, nil, pur.d.err + } + + return urr.ut, urr.data, nil +} |