-
Notifications
You must be signed in to change notification settings - Fork 11
/
types.go
149 lines (130 loc) · 3.15 KB
/
types.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright 2015-2017 Jean Niklas L'orange. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package edn
import (
"bufio"
"bytes"
"errors"
"fmt"
)
// RawMessage is a raw encoded, but valid, EDN value. It implements Marshaler
// and Unmarshaler and can be used to delay EDN decoding or precompute an EDN
// encoding.
type RawMessage []byte
// MarshalEDN returns m as the EDN encoding of m.
func (m RawMessage) MarshalEDN() ([]byte, error) {
if m == nil {
return []byte("nil"), nil
}
return m, nil
}
// UnmarshalEDN sets *m to a copy of data.
func (m *RawMessage) UnmarshalEDN(data []byte) error {
if m == nil {
return errors.New("edn.RawMessage: UnmarshalEDN on nil pointer")
}
*m = append((*m)[0:0], data...)
return nil
}
// A Keyword is an EDN keyword without : prepended in front.
type Keyword string
func (k Keyword) String() string {
return fmt.Sprintf(":%s", string(k))
}
func (k Keyword) MarshalEDN() ([]byte, error) {
return []byte(k.String()), nil
}
// A Symbol is an EDN symbol.
type Symbol string
func (s Symbol) String() string {
return string(s)
}
func (s Symbol) MarshalEDN() ([]byte, error) {
return []byte(s), nil
}
// A Tag is a tagged value. The Tagname represents the name of the tag, and the
// Value is the value of the element.
type Tag struct {
Tagname string
Value interface{}
}
func (t Tag) String() string {
return fmt.Sprintf("#%s %v", t.Tagname, t.Value)
}
func (t Tag) MarshalEDN() ([]byte, error) {
str := []byte(fmt.Sprintf(`#%s `, t.Tagname))
b, err := Marshal(t.Value)
if err != nil {
return nil, err
}
return append(str, b...), nil
}
func (t *Tag) UnmarshalEDN(bs []byte) error {
// read actual tag, using the lexer.
var lex lexer
lex.reset()
buf := bufio.NewReader(bytes.NewBuffer(bs))
start := 0
endTag := 0
tag:
for {
r, rlen, err := buf.ReadRune()
if err != nil {
return err
}
ls := lex.state(r)
switch ls {
case lexIgnore:
start += rlen
endTag += rlen
case lexError:
return lex.err
case lexEndPrev:
break tag
case lexEnd: // unexpected, assuming tag which is not ending with lexEnd
return errUnexpected
case lexCont:
endTag += rlen
}
}
t.Tagname = string(bs[start+1 : endTag])
return Unmarshal(bs[endTag:], &t.Value)
}
// A Rune type is a wrapper for a rune. It can be used to encode runes as
// characters instead of int32 values.
type Rune rune
func (r Rune) MarshalEDN() ([]byte, error) {
buf := bytes.NewBuffer(make([]byte, 0, 10))
encodeRune(buf, rune(r))
return buf.Bytes(), nil
}
func encodeRune(buf *bytes.Buffer, r rune) {
const hex = "0123456789abcdef"
if !isWhitespace(r) {
buf.WriteByte('\\')
buf.WriteRune(r)
} else {
switch r {
case '\b':
buf.WriteString(`\backspace`)
case '\f':
buf.WriteString(`\formfeed`)
case '\n':
buf.WriteString(`\newline`)
case '\r':
buf.WriteString(`\return`)
case '\t':
buf.WriteString(`\tab`)
case ' ':
buf.WriteString(`\space`)
default:
buf.WriteByte('\\')
buf.WriteByte('u')
buf.WriteByte(hex[r>>12&0xF])
buf.WriteByte(hex[r>>8&0xF])
buf.WriteByte(hex[r>>4&0xF])
buf.WriteByte(hex[r&0xF])
}
}
}