forked from rclone/rclone
-
Notifications
You must be signed in to change notification settings - Fork 3
/
internal.go
156 lines (142 loc) · 3.11 KB
/
internal.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
150
151
152
153
154
155
156
package internal
import (
"bytes"
"encoding/json"
"fmt"
"strings"
)
// Presence describes the presence of a filename in file listing
type Presence int
// Possible Presence states
const (
Absent Presence = iota
Present
Renamed
Multiple
)
// Position is the placement of the test character in the filename
type Position int
// Predefined positions
const (
PositionMiddle Position = 1 << iota
PositionLeft
PositionRight
PositionNone Position = 0
PositionAll Position = PositionRight<<1 - 1
)
// PositionList contains all valid positions
var PositionList = []Position{PositionMiddle, PositionLeft, PositionRight}
// ControlResult contains the result of a single character test
type ControlResult struct {
Text string `json:"-"`
WriteError map[Position]string
GetError map[Position]string
InList map[Position]Presence
}
// InfoReport is the structure of the JSON output
type InfoReport struct {
Remote string
ControlCharacters *map[string]ControlResult
MaxFileLength *int
CanStream *bool
CanWriteUnnormalized *bool
CanReadUnnormalized *bool
CanReadRenormalized *bool
}
func (e Position) String() string {
switch e {
case PositionNone:
return "none"
case PositionAll:
return "all"
}
var buf bytes.Buffer
if e&PositionMiddle != 0 {
buf.WriteString("middle")
e &= ^PositionMiddle
}
if e&PositionLeft != 0 {
if buf.Len() != 0 {
buf.WriteRune(',')
}
buf.WriteString("left")
e &= ^PositionLeft
}
if e&PositionRight != 0 {
if buf.Len() != 0 {
buf.WriteRune(',')
}
buf.WriteString("right")
e &= ^PositionRight
}
if e != PositionNone {
panic("invalid position")
}
return buf.String()
}
// MarshalText encodes the position when used as a map key
func (e Position) MarshalText() ([]byte, error) {
return []byte(e.String()), nil
}
// UnmarshalText decodes a position when used as a map key
func (e *Position) UnmarshalText(text []byte) error {
switch s := strings.ToLower(string(text)); s {
default:
*e = PositionNone
for _, p := range strings.Split(s, ",") {
switch p {
case "left":
*e |= PositionLeft
case "middle":
*e |= PositionMiddle
case "right":
*e |= PositionRight
default:
return fmt.Errorf("unknown position: %s", e)
}
}
case "none":
*e = PositionNone
case "all":
*e = PositionAll
}
return nil
}
func (e Presence) String() string {
switch e {
case Absent:
return "absent"
case Present:
return "present"
case Renamed:
return "renamed"
case Multiple:
return "multiple"
default:
panic("invalid presence")
}
}
// MarshalJSON encodes the presence when used as a JSON value
func (e Presence) MarshalJSON() ([]byte, error) {
return json.Marshal(e.String())
}
// UnmarshalJSON decodes a presence when used as a JSON value
func (e *Presence) UnmarshalJSON(text []byte) error {
var s string
if err := json.Unmarshal(text, &s); err != nil {
return err
}
switch s := strings.ToLower(s); s {
case "absent":
*e = Absent
case "present":
*e = Present
case "renamed":
*e = Renamed
case "multiple":
*e = Multiple
default:
return fmt.Errorf("unknown presence: %s", e)
}
return nil
}