62 lines
1.2 KiB
Go
62 lines
1.2 KiB
Go
package gophermap
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"tildegit.org/tjp/gus"
|
|
"tildegit.org/tjp/gus/gopher"
|
|
)
|
|
|
|
// Parse reads a gophermap document from a reader.
|
|
func Parse(input io.Reader) (gopher.MapDocument, error) {
|
|
rdr := bufio.NewReader(input)
|
|
doc := gopher.MapDocument{}
|
|
|
|
num := 0
|
|
for {
|
|
num += 1
|
|
line, err := rdr.ReadBytes('\n')
|
|
isEOF := errors.Is(err, io.EOF)
|
|
if err != nil && !isEOF {
|
|
return nil, err
|
|
}
|
|
|
|
if len(line) > 2 && !bytes.Equal(line, []byte(".\r\n")) {
|
|
if line[len(line)-2] != '\r' || line[len(line)-1] != '\n' {
|
|
return nil, InvalidLine(num)
|
|
}
|
|
|
|
item := gopher.MapItem{Type: gus.Status(line[0])}
|
|
|
|
spl := bytes.Split(line[1:len(line)-2], []byte{'\t'})
|
|
if len(spl) != 4 {
|
|
return nil, InvalidLine(num)
|
|
}
|
|
item.Display = string(spl[0])
|
|
item.Selector = string(spl[1])
|
|
item.Hostname = string(spl[2])
|
|
item.Port = string(spl[3])
|
|
|
|
doc = append(doc, item)
|
|
}
|
|
|
|
if isEOF {
|
|
break
|
|
}
|
|
}
|
|
|
|
return doc, nil
|
|
}
|
|
|
|
// InvalidLine is returned from Parse when the reader contains a line which is invalid gophermap.
|
|
type InvalidLine int
|
|
|
|
// Error implements the error interface.
|
|
func (il InvalidLine) Error() string {
|
|
return fmt.Sprintf("Invalid gophermap on line %d.", il)
|
|
}
|