1// Copyright 2015-2017 Jean Niklas L'orange.  All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package edn
6
7import (
8	"bufio"
9	"bytes"
10	"errors"
11	"fmt"
12)
13
14// RawMessage is a raw encoded, but valid, EDN value. It implements Marshaler
15// and Unmarshaler and can be used to delay EDN decoding or precompute an EDN
16// encoding.
17type RawMessage []byte
18
19// MarshalEDN returns m as the EDN encoding of m.
20func (m RawMessage) MarshalEDN() ([]byte, error) {
21	if m == nil {
22		return []byte("nil"), nil
23	}
24	return m, nil
25}
26
27// UnmarshalEDN sets *m to a copy of data.
28func (m *RawMessage) UnmarshalEDN(data []byte) error {
29	if m == nil {
30		return errors.New("edn.RawMessage: UnmarshalEDN on nil pointer")
31	}
32	*m = append((*m)[0:0], data...)
33	return nil
34}
35
36// A Keyword is an EDN keyword without : prepended in front.
37type Keyword string
38
39func (k Keyword) String() string {
40	return fmt.Sprintf(":%s", string(k))
41}
42
43func (k Keyword) MarshalEDN() ([]byte, error) {
44	return []byte(k.String()), nil
45}
46
47// A Symbol is an EDN symbol.
48type Symbol string
49
50func (s Symbol) String() string {
51	return string(s)
52}
53
54func (s Symbol) MarshalEDN() ([]byte, error) {
55	return []byte(s), nil
56}
57
58// A Tag is a tagged value. The Tagname represents the name of the tag, and the
59// Value is the value of the element.
60type Tag struct {
61	Tagname string
62	Value   interface{}
63}
64
65func (t Tag) String() string {
66	return fmt.Sprintf("#%s %v", t.Tagname, t.Value)
67}
68
69func (t Tag) MarshalEDN() ([]byte, error) {
70	str := []byte(fmt.Sprintf(`#%s `, t.Tagname))
71	b, err := Marshal(t.Value)
72	if err != nil {
73		return nil, err
74	}
75	return append(str, b...), nil
76}
77
78func (t *Tag) UnmarshalEDN(bs []byte) error {
79	// read actual tag, using the lexer.
80	var lex lexer
81	lex.reset()
82	buf := bufio.NewReader(bytes.NewBuffer(bs))
83	start := 0
84	endTag := 0
85tag:
86	for {
87		r, rlen, err := buf.ReadRune()
88		if err != nil {
89			return err
90		}
91
92		ls := lex.state(r)
93		switch ls {
94		case lexIgnore:
95			start += rlen
96			endTag += rlen
97		case lexError:
98			return lex.err
99		case lexEndPrev:
100			break tag
101		case lexEnd: // unexpected, assuming tag which is not ending with lexEnd
102			return errUnexpected
103		case lexCont:
104			endTag += rlen
105		}
106	}
107	t.Tagname = string(bs[start+1 : endTag])
108	return Unmarshal(bs[endTag:], &t.Value)
109}
110
111// A Rune type is a wrapper for a rune. It can be used to encode runes as
112// characters instead of int32 values.
113type Rune rune
114
115func (r Rune) MarshalEDN() ([]byte, error) {
116	buf := bytes.NewBuffer(make([]byte, 0, 10))
117	encodeRune(buf, rune(r))
118	return buf.Bytes(), nil
119}
120
121func encodeRune(buf *bytes.Buffer, r rune) {
122	const hex = "0123456789abcdef"
123	if !isWhitespace(r) {
124		buf.WriteByte('\\')
125		buf.WriteRune(r)
126	} else {
127		switch r {
128		case '\b':
129			buf.WriteString(`\backspace`)
130		case '\f':
131			buf.WriteString(`\formfeed`)
132		case '\n':
133			buf.WriteString(`\newline`)
134		case '\r':
135			buf.WriteString(`\return`)
136		case '\t':
137			buf.WriteString(`\tab`)
138		case ' ':
139			buf.WriteString(`\space`)
140		default:
141			buf.WriteByte('\\')
142			buf.WriteByte('u')
143			buf.WriteByte(hex[r>>12&0xF])
144			buf.WriteByte(hex[r>>8&0xF])
145			buf.WriteByte(hex[r>>4&0xF])
146			buf.WriteByte(hex[r&0xF])
147		}
148	}
149}
150