-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathswitch.go
220 lines (208 loc) · 5.29 KB
/
switch.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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
package finger
import (
"fmt"
)
// Switch is used to hold a finger-protocol request ‘switch’.
//
// Note that Switch is implemented as an optional-type.
// (Which in other programming languages is called a option-type or a maybe-type.)
//
// ⁂
//
// Most people are probably only going to use Switch as part
// of finger.Request.
//
// I.e,.
//
// func (receiver *MyFingerHandler) HandleFinger(rw finger.ResponseWriter, request finger.Request) {
//
// // ...
//
// fmt.Printf("finger request switch: %#v", request.Switch)
//
// // ...
//
// swtch, something := request.Switch.Unwrap()
//
// // ...
//
// }
//
// ⁂
//
// For debugging, one can see the value (or lack of a value) of a Switch with code like
// the following:
//
// fmt.Printf("finger request switch: %#v", swtch)
//
// Notice that the verb being used is “%#v” (and not just “%v”).
//
// ⁂
//
// To get a value out of a Switch, do something like the following:
//
// var swtch finger.Switch
//
// // ...
//
// value, something := swtch.Unwrap()
// if something {
// // a value was set for the finger.Switch
// } else {
// // no value was set for the finger.Switch
// }
//
// Note that this is unwrapping the Switch optional-type.
//
// ⁂
//
// One type of finger-protocol request looks like:
//
// "/W joeblow\r\n"
//
// Another type of finger-protocol request looks like:
//
// "/W\r\n"
//
// (There are other types of finger-protocol requests, but they aren't relevant here.)
//
// The "/W" is a finger-protocol request ‘switch’.
// (It is actually the only finger-protocol request ‘switch’ mentioned in the
// IETF RFC-742 & IETF RFC-1288 specifications.)
//
// For each of these finger-protocol requests, what would be stored in the code (for finger.Switch) is:
//
// var swtch finger.Switch = finger.CreateSwitch("/W")
//
// ⁂
//
// Although the IETF RFCs for finger only mentions the “/W” finger-protocol
// request ‘switch’ — if an incoming finger-protocol request has a different
// finger-protocol request ‘switch’, Switch can store it.
//
// For example, if an incoming finger-protocol request was:
//
// "/PULL joeblow\r\n"
//
// Then Switch would logically be:
//
// var swtch finger.Switch = finger.CreateSwitch("/PULL")
//
// ⁂
//
// IETF RFCs say the following about finger-protocol request ‘switches’ —
//
// The older IETF RFC-742 says:
//
// “if "/W" (called the "Whois switch") also appears on the line given to an
// ITS server, much fuller descriptions are returned.”
//
// And the newer IETF RFC-1288 says:
//
// “The token /W in the {Q1} or {Q2} query types SHOULD at best be interpreted
// at the last RUIP to signify a higher level of verbosity in the user
// information output, or at worst be ignored.”
type Switch struct {
value string
something bool
}
// EmptySwitch is used to create a finger.Switch with nothing in it.
func EmptySwitch() Switch {
return Switch{}
}
// CreateSwitch is used to create a finger.Switch with something in it.
func CreateSwitch(value string) Switch {
return Switch{
value:value,
something:true,
}
}
// ParseSwitch parses a finger-protocol swtch from a string.
//
// Example usage:
//
// var swtichString string = "/W"
//
// swtch, err := finger.ParseSwitch(switchString)
//
// Anoter example usage:
//
// var swtichString string = "/PULL"
//
// swtch, err := finger.ParseSwitch(switchString)
//
// Some example finger-protocol requests with switches are:
//
// "/W\r\n"
//
// "/W joeblow\r\n"
//
// "/W dariush\r\n"
//
// "/W [email protected]\r\n"
//
// "/W [email protected]\r\n"
//
// Those examples all have the "/W" switch.
//
// The "/W" switch is the only switch that IETF RFC-742 and IEFT RFC-1288 specify.
// But neither IETF RFC-742 and IEFT RFC-1288 prohibit other switches.
//
// Thus a finger-protocol client could send an alternative finger-protocol switch.
//
// And a finger-protocol server could handle an alternative finger-protocol switch.
func ParseSwitch(s string) (Switch, error) {
if "" == s {
return EmptySwitch(), errSlashNotFound
}
if '/' != s[0] {
return EmptySwitch(), errSlashNotFound
}
return CreateSwitch(s), nil
}
func (receiver Switch) String() string {
if !receiver.something {
return ""
}
return fmt.Sprintf("%s", receiver.value)
}
// Unwrap is used to unwrap a finger.Switch.
//
// value, something := swtch.Unwrap()
//
// If finger.Switch is holding something, then ‘something’ (in the code above) is ‘true’.
//
// If finger.Switch is holding nothing, then ‘something’ (in the code above) is ‘false’.
func (receiver Switch) Unwrap() (string, bool) {
return receiver.value, receiver.something
}
// GoString makes it so that when the fmt.Fprintf(), fmt.Printf(), and fmt.Sprintf() family of functions
// renders this type with the %#v verb, that it will be easier to understand.
//
// For example:
//
// var swtch finger.Switch = finger.CreateSwitch("/W")
//
// // ...
//
// fmt.Printf("swtch = %#v", swtch)
//
// // Output:
// // swtch = finger.CreateSwitch("/W")
//
// Also, for example:
//
// var swtch finger.Switch = finger.EmptySwitch()
//
// // ...
//
// fmt.Printf("swtch = %#v", swtch)
//
// // Output:
// // swtch = finger.EmptySwitch()
func (receiver Switch) GoString() string {
if !receiver.something {
return "finger.EmptySwitch()"
}
return fmt.Sprintf("finger.CreateSwitch(%#v)", receiver.value)
}