gofront 1.7.0 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. package/README.md +14 -14
  2. package/package.json +10 -38
  3. package/src/backend/js/expressions.js +2060 -389
  4. package/src/backend/js/index.js +586 -174
  5. package/src/backend/js/natives.js +383 -0
  6. package/src/backend/js/runtime.js +936 -1644
  7. package/src/backend/js/statements.js +1349 -132
  8. package/src/backend/js/stdlib/index.js +51 -94
  9. package/src/backend/js/templ.js +67 -118
  10. package/src/backend/js/type-info.js +436 -0
  11. package/src/backend/shared/fixed-float.js +20 -0
  12. package/src/backend/shared/fmt-types.js +80 -0
  13. package/src/backend/shared/host-unicode.js +36 -0
  14. package/src/backend/wasm/boundary.js +753 -872
  15. package/src/backend/wasm/emit-builtins.js +914 -237
  16. package/src/backend/wasm/emit-exprs.js +1456 -195
  17. package/src/backend/wasm/emit-maps.js +78 -380
  18. package/src/backend/wasm/emit-stmts.js +1659 -214
  19. package/src/backend/wasm/emit.js +614 -88
  20. package/src/backend/wasm/encode.js +43 -13
  21. package/src/backend/wasm/globals.js +491 -0
  22. package/src/backend/wasm/glue.js +2 -4
  23. package/src/backend/wasm/index.js +406 -3195
  24. package/src/backend/wasm/method-expr.js +392 -0
  25. package/src/backend/wasm/module-emitter.js +1615 -0
  26. package/src/backend/wasm/monomorph.js +164 -9
  27. package/src/backend/wasm/natives.js +596 -0
  28. package/src/backend/wasm/prescan.js +249 -0
  29. package/src/backend/wasm/prune-funcs.js +89 -0
  30. package/src/backend/wasm/stdlib/index.js +2 -37
  31. package/src/backend/wasm/stdlib/simd.js +293 -28
  32. package/src/backend/wasm/types.js +260 -27
  33. package/src/backend/wasm/variadic.js +93 -0
  34. package/src/backend/wasm/wat.js +47 -20
  35. package/src/{cli-core.js → cli/cli-core.js} +241 -11
  36. package/src/{test-runner.js → cli/test-runner.js} +188 -122
  37. package/src/{vendor.js → cli/vendor.js} +3 -4
  38. package/src/compiler.js +202 -386
  39. package/src/index.js +15 -169
  40. package/src/{lexer.js → lexer/lexer.js} +203 -62
  41. package/src/{templ-lexer.js → lexer/templ-lexer.js} +61 -18
  42. package/src/{tokens.js → lexer/tokens.js} +2 -0
  43. package/src/link/sourcemap.js +97 -0
  44. package/src/link/stdlib.js +737 -0
  45. package/src/link/type-names.js +148 -0
  46. package/src/link/wasm.js +318 -0
  47. package/src/lower/bounds.js +547 -0
  48. package/src/lower/boxing.js +1 -1
  49. package/src/lower/captures.js +267 -64
  50. package/src/lower/embedding.js +32 -3
  51. package/src/lower/errors-as.js +196 -0
  52. package/src/lower/fmt-formatters.js +905 -0
  53. package/src/lower/functions.js +2 -0
  54. package/src/lower/gen-types.js +274 -0
  55. package/src/lower/index.js +33 -19
  56. package/src/lower/json-codecs.js +1379 -0
  57. package/src/lower/ownership.js +47 -8
  58. package/src/lower/range.js +86 -1
  59. package/src/lower/reachability.js +150 -0
  60. package/src/lower/walk.js +12 -0
  61. package/src/parser/declarations.js +83 -15
  62. package/src/parser/expressions.js +110 -18
  63. package/src/parser/index.js +2 -1
  64. package/src/parser/statements.js +38 -22
  65. package/src/{templ-parser.js → parser/templ.js} +179 -17
  66. package/src/parser/types.js +70 -9
  67. package/src/resolver.js +21 -1
  68. package/src/typechecker/assignability.js +291 -19
  69. package/src/typechecker/const-fold.js +399 -0
  70. package/src/typechecker/constants.js +282 -0
  71. package/src/typechecker/expressions.js +1220 -183
  72. package/src/typechecker/index.js +659 -92
  73. package/src/typechecker/init-order.js +426 -0
  74. package/src/typechecker/operand-text.js +40 -0
  75. package/src/typechecker/resolve.js +613 -62
  76. package/src/typechecker/statements.js +212 -20
  77. package/src/typechecker/stdlib/excluded.js +902 -0
  78. package/src/typechecker/stdlib/index.js +38 -0
  79. package/src/typechecker/stdlib/simd.js +65 -15
  80. package/src/typechecker/termination.js +11 -2
  81. package/src/typechecker/types.js +268 -514
  82. package/stdlib/bytes/buffer.go +479 -0
  83. package/stdlib/bytes/bytes.go +1010 -0
  84. package/stdlib/bytes/reader.go +161 -0
  85. package/stdlib/cmp/cmp.go +65 -0
  86. package/stdlib/context/context.go +115 -0
  87. package/stdlib/crypto/rand/rand.go +34 -0
  88. package/stdlib/crypto/sha256/sha256.go +249 -0
  89. package/stdlib/encoding/base64/base64.go +331 -0
  90. package/stdlib/encoding/binary/binary.go +332 -0
  91. package/stdlib/encoding/hex/hex.go +140 -0
  92. package/stdlib/encoding/json/errors.go +31 -0
  93. package/stdlib/encoding/json/indent.go +71 -0
  94. package/stdlib/encoding/json/json.go +62 -0
  95. package/stdlib/encoding/json/number.go +12 -0
  96. package/stdlib/encoding/json/stream.go +173 -0
  97. package/stdlib/errors/errors.go +174 -0
  98. package/stdlib/fmt/errors.go +110 -0
  99. package/stdlib/fmt/format.go +732 -0
  100. package/stdlib/fmt/print.go +1232 -0
  101. package/stdlib/gom/gom.go +293 -0
  102. package/stdlib/hash/hash.go +53 -0
  103. package/stdlib/html/html.go +251 -0
  104. package/stdlib/internal/fmtrt/fmtrt.go +163 -0
  105. package/stdlib/internal/jsonrt/dec.go +871 -0
  106. package/stdlib/internal/jsonrt/enc.go +516 -0
  107. package/stdlib/internal/jsonrt/indent.go +135 -0
  108. package/stdlib/internal/jsonrt/number.go +27 -0
  109. package/stdlib/internal/jsonrt/reader.go +73 -0
  110. package/stdlib/internal/jsonrt/scanner.go +658 -0
  111. package/stdlib/io/io.go +502 -0
  112. package/stdlib/iter/iter.go +18 -0
  113. package/stdlib/maps/maps.go +131 -0
  114. package/stdlib/math/bits/bits.go +507 -0
  115. package/stdlib/math/extra.go +272 -0
  116. package/stdlib/math/math.go +439 -0
  117. package/stdlib/math/rand/rand.go +297 -0
  118. package/stdlib/os/os.go +93 -0
  119. package/stdlib/path/filepath/filepath.go +47 -0
  120. package/stdlib/path/path.go +394 -0
  121. package/stdlib/regexp/regexp.go +231 -0
  122. package/stdlib/slices/slices.go +526 -0
  123. package/stdlib/slices/sort.go +209 -0
  124. package/stdlib/slices/zsort_cmp.go +480 -0
  125. package/stdlib/slices/zsort_ordered.go +482 -0
  126. package/stdlib/sort/sort.go +500 -0
  127. package/stdlib/sort/zsort_func.go +480 -0
  128. package/stdlib/sort/zsort_iface.go +480 -0
  129. package/stdlib/strconv/float.go +1699 -0
  130. package/stdlib/strconv/isprint.go +752 -0
  131. package/stdlib/strconv/quote.go +526 -0
  132. package/stdlib/strconv/strconv.go +616 -0
  133. package/stdlib/strings/builder.go +95 -0
  134. package/stdlib/strings/reader.go +163 -0
  135. package/stdlib/strings/replacer.go +102 -0
  136. package/stdlib/strings/strings.go +807 -0
  137. package/stdlib/sync/sync.go +268 -0
  138. package/stdlib/testing/async_js.go +61 -0
  139. package/stdlib/testing/benchmark.go +297 -0
  140. package/stdlib/testing/testing.go +523 -0
  141. package/stdlib/time/duration.go +233 -0
  142. package/stdlib/time/format.go +745 -0
  143. package/stdlib/time/parse.go +790 -0
  144. package/stdlib/time/sleep_js.go +63 -0
  145. package/stdlib/time/time.go +834 -0
  146. package/stdlib/unicode/unicode.go +250 -0
  147. package/stdlib/unicode/utf8/utf8.go +464 -0
  148. package/src/backend/js/stdlib/base64.js +0 -12
  149. package/src/backend/js/stdlib/binary.js +0 -102
  150. package/src/backend/js/stdlib/bits.js +0 -46
  151. package/src/backend/js/stdlib/builder.js +0 -63
  152. package/src/backend/js/stdlib/bytes.js +0 -122
  153. package/src/backend/js/stdlib/errors.js +0 -44
  154. package/src/backend/js/stdlib/fmt.js +0 -178
  155. package/src/backend/js/stdlib/gom.js +0 -155
  156. package/src/backend/js/stdlib/hex.js +0 -17
  157. package/src/backend/js/stdlib/html.js +0 -20
  158. package/src/backend/js/stdlib/io.js +0 -137
  159. package/src/backend/js/stdlib/json.js +0 -972
  160. package/src/backend/js/stdlib/maps.js +0 -45
  161. package/src/backend/js/stdlib/math.js +0 -69
  162. package/src/backend/js/stdlib/os.js +0 -13
  163. package/src/backend/js/stdlib/path.js +0 -48
  164. package/src/backend/js/stdlib/rand.js +0 -32
  165. package/src/backend/js/stdlib/regexp.js +0 -54
  166. package/src/backend/js/stdlib/sha256.js +0 -12
  167. package/src/backend/js/stdlib/shared.js +0 -17
  168. package/src/backend/js/stdlib/simd.js +0 -24
  169. package/src/backend/js/stdlib/slices.js +0 -77
  170. package/src/backend/js/stdlib/sort.js +0 -30
  171. package/src/backend/js/stdlib/strconv.js +0 -74
  172. package/src/backend/js/stdlib/strings.js +0 -222
  173. package/src/backend/js/stdlib/sync.js +0 -13
  174. package/src/backend/js/stdlib/testing.js +0 -34
  175. package/src/backend/js/stdlib/time.js +0 -128
  176. package/src/backend/js/stdlib/unicode.js +0 -25
  177. package/src/backend/js/stdlib/utf8.js +0 -26
  178. package/src/backend/wasm/const-fold.js +0 -205
  179. package/src/backend/wasm/emit-stdlib.js +0 -13
  180. package/src/backend/wasm/stdlib/bytes.js +0 -5039
  181. package/src/backend/wasm/stdlib/core.js +0 -8903
  182. package/src/backend/wasm/stdlib/io.js +0 -2161
  183. package/src/backend/wasm/stdlib/packages.js +0 -2400
  184. package/src/backend/wasm/stdlib/pure.js +0 -720
  185. package/src/backend/wasm/stdlib/time.js +0 -1200
  186. package/src/typechecker/stdlib/core.js +0 -801
  187. package/src/typechecker/stdlib/extended.js +0 -914
  188. package/src/typechecker/stdlib.js +0 -22
  189. /package/src/{asset-manager.js → cli/asset-manager.js} +0 -0
  190. /package/src/{colors.js → cli/colors.js} +0 -0
  191. /package/src/{dev-server.js → cli/dev-server.js} +0 -0
  192. /package/src/{minifier.js → cli/minifier.js} +0 -0
  193. /package/src/{project-config.js → cli/project-config.js} +0 -0
  194. /package/src/{pwa.js → cli/pwa.js} +0 -0
@@ -0,0 +1,745 @@
1
+ //go:build gofront
2
+
3
+ //gofront:target both
4
+
5
+ // Copyright 2010 The Go Authors. All rights reserved.
6
+ // Use of this source code is governed by a BSD-style
7
+ // license that can be found in the LICENSE file.
8
+
9
+ package time
10
+
11
+ import "errors"
12
+
13
+ // These are predefined layouts for use in Time.Format and time.Parse. The
14
+ // reference time used in these layouts is the specific time stamp:
15
+ //
16
+ // 01/02 03:04:05PM '06 -0700
17
+ //
18
+ // (January 2, 15:04:05, 2006, in time zone seven hours west of GMT).
19
+ const (
20
+ Layout = "01/02 03:04:05PM '06 -0700" // The reference time, in numerical order.
21
+ ANSIC = "Mon Jan _2 15:04:05 2006"
22
+ UnixDate = "Mon Jan _2 15:04:05 MST 2006"
23
+ RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
24
+ RFC822 = "02 Jan 06 15:04 MST"
25
+ RFC822Z = "02 Jan 06 15:04 -0700" // RFC822 with numeric zone
26
+ RFC850 = "Monday, 02-Jan-06 15:04:05 MST"
27
+ RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
28
+ RFC1123Z = "Mon, 02 Jan 2006 15:04:05 -0700" // RFC1123 with numeric zone
29
+ RFC3339 = "2006-01-02T15:04:05Z07:00"
30
+ RFC3339Nano = "2006-01-02T15:04:05.999999999Z07:00"
31
+ Kitchen = "3:04PM"
32
+ // Handy time stamps.
33
+ Stamp = "Jan _2 15:04:05"
34
+ StampMilli = "Jan _2 15:04:05.000"
35
+ StampMicro = "Jan _2 15:04:05.000000"
36
+ StampNano = "Jan _2 15:04:05.000000000"
37
+ DateTime = "2006-01-02 15:04:05"
38
+ DateOnly = "2006-01-02"
39
+ TimeOnly = "15:04:05"
40
+ )
41
+
42
+ const (
43
+ _ = iota
44
+ stdLongMonth = iota + stdNeedDate // "January"
45
+ stdMonth // "Jan"
46
+ stdNumMonth // "1"
47
+ stdZeroMonth // "01"
48
+ stdLongWeekDay // "Monday"
49
+ stdWeekDay // "Mon"
50
+ stdDay // "2"
51
+ stdUnderDay // "_2"
52
+ stdZeroDay // "02"
53
+ stdUnderYearDay // "__2"
54
+ stdZeroYearDay // "002"
55
+ stdHour = iota + stdNeedClock // "15"
56
+ stdHour12 // "3"
57
+ stdZeroHour12 // "03"
58
+ stdMinute // "4"
59
+ stdZeroMinute // "04"
60
+ stdSecond // "5"
61
+ stdZeroSecond // "05"
62
+ stdLongYear = iota + stdNeedDate // "2006"
63
+ stdYear // "06"
64
+ stdPM = iota + stdNeedClock // "PM"
65
+ stdpm // "pm"
66
+ stdTZ = iota // "MST"
67
+ stdISO8601TZ // "Z0700" // prints Z for UTC
68
+ stdISO8601SecondsTZ // "Z070000"
69
+ stdISO8601ShortTZ // "Z07"
70
+ stdISO8601ColonTZ // "Z07:00" // prints Z for UTC
71
+ stdISO8601ColonSecondsTZ // "Z07:00:00"
72
+ stdNumTZ // "-0700" // always numeric
73
+ stdNumSecondsTz // "-070000"
74
+ stdNumShortTZ // "-07" // always numeric
75
+ stdNumColonTZ // "-07:00" // always numeric
76
+ stdNumColonSecondsTZ // "-07:00:00"
77
+ stdFracSecond0 // ".0", ".00", ... , trailing zeros included
78
+ stdFracSecond9 // ".9", ".99", ..., trailing zeros omitted
79
+
80
+ stdNeedDate = 1 << 8 // need month, day, year
81
+ stdNeedClock = 2 << 8 // need hour, minute, second
82
+ stdArgShift = 16 // extra argument in high bits, above low stdArgShift
83
+ stdSeparatorShift = 28 // extra argument in high 4 bits for fractional second separators
84
+ stdMask = 1<<stdArgShift - 1 // mask out argument
85
+ )
86
+
87
+ // std0x records the std values for "01", "02", ..., "06".
88
+ var std0x = [6]int{stdZeroMonth, stdZeroDay, stdZeroHour12, stdZeroMinute, stdZeroSecond, stdYear}
89
+
90
+ // startsWithLowerCase reports whether the string has a lower-case letter at the beginning.
91
+ // Its purpose is to prevent matching strings like "Month" when looking for "Mon".
92
+ func startsWithLowerCase(str string) bool {
93
+ if len(str) == 0 {
94
+ return false
95
+ }
96
+ c := str[0]
97
+ return 'a' <= c && c <= 'z'
98
+ }
99
+
100
+ // nextStdChunk finds the first occurrence of a std string in
101
+ // layout and returns the text before, the std string, and the text after.
102
+ func nextStdChunk(layout string) (prefix string, std int, suffix string) {
103
+ for i := 0; i < len(layout); i++ {
104
+ switch c := int(layout[i]); c {
105
+ case 'J': // January, Jan
106
+ if len(layout) >= i+3 && layout[i:i+3] == "Jan" {
107
+ if len(layout) >= i+7 && layout[i:i+7] == "January" {
108
+ return layout[0:i], stdLongMonth, layout[i+7:]
109
+ }
110
+ if !startsWithLowerCase(layout[i+3:]) {
111
+ return layout[0:i], stdMonth, layout[i+3:]
112
+ }
113
+ }
114
+
115
+ case 'M': // Monday, Mon, MST
116
+ if len(layout) >= i+3 {
117
+ if layout[i:i+3] == "Mon" {
118
+ if len(layout) >= i+6 && layout[i:i+6] == "Monday" {
119
+ return layout[0:i], stdLongWeekDay, layout[i+6:]
120
+ }
121
+ if !startsWithLowerCase(layout[i+3:]) {
122
+ return layout[0:i], stdWeekDay, layout[i+3:]
123
+ }
124
+ }
125
+ if layout[i:i+3] == "MST" {
126
+ return layout[0:i], stdTZ, layout[i+3:]
127
+ }
128
+ }
129
+
130
+ case '0': // 01, 02, 03, 04, 05, 06, 002
131
+ if len(layout) >= i+2 && '1' <= layout[i+1] && layout[i+1] <= '6' {
132
+ return layout[0:i], std0x[layout[i+1]-'1'], layout[i+2:]
133
+ }
134
+ if len(layout) >= i+3 && layout[i+1] == '0' && layout[i+2] == '2' {
135
+ return layout[0:i], stdZeroYearDay, layout[i+3:]
136
+ }
137
+
138
+ case '1': // 15, 1
139
+ if len(layout) >= i+2 && layout[i+1] == '5' {
140
+ return layout[0:i], stdHour, layout[i+2:]
141
+ }
142
+ return layout[0:i], stdNumMonth, layout[i+1:]
143
+
144
+ case '2': // 2006, 2
145
+ if len(layout) >= i+4 && layout[i:i+4] == "2006" {
146
+ return layout[0:i], stdLongYear, layout[i+4:]
147
+ }
148
+ return layout[0:i], stdDay, layout[i+1:]
149
+
150
+ case '_': // _2, _2006, __2
151
+ if len(layout) >= i+2 && layout[i+1] == '2' {
152
+ //_2006 is really a literal _, followed by stdLongYear
153
+ if len(layout) >= i+5 && layout[i+1:i+5] == "2006" {
154
+ return layout[0 : i+1], stdLongYear, layout[i+5:]
155
+ }
156
+ return layout[0:i], stdUnderDay, layout[i+2:]
157
+ }
158
+ if len(layout) >= i+3 && layout[i+1] == '_' && layout[i+2] == '2' {
159
+ return layout[0:i], stdUnderYearDay, layout[i+3:]
160
+ }
161
+
162
+ case '3':
163
+ return layout[0:i], stdHour12, layout[i+1:]
164
+
165
+ case '4':
166
+ return layout[0:i], stdMinute, layout[i+1:]
167
+
168
+ case '5':
169
+ return layout[0:i], stdSecond, layout[i+1:]
170
+
171
+ case 'P': // PM
172
+ if len(layout) >= i+2 && layout[i+1] == 'M' {
173
+ return layout[0:i], stdPM, layout[i+2:]
174
+ }
175
+
176
+ case 'p': // pm
177
+ if len(layout) >= i+2 && layout[i+1] == 'm' {
178
+ return layout[0:i], stdpm, layout[i+2:]
179
+ }
180
+
181
+ case '-': // -070000, -07:00:00, -0700, -07:00, -07
182
+ if len(layout) >= i+7 && layout[i:i+7] == "-070000" {
183
+ return layout[0:i], stdNumSecondsTz, layout[i+7:]
184
+ }
185
+ if len(layout) >= i+9 && layout[i:i+9] == "-07:00:00" {
186
+ return layout[0:i], stdNumColonSecondsTZ, layout[i+9:]
187
+ }
188
+ if len(layout) >= i+5 && layout[i:i+5] == "-0700" {
189
+ return layout[0:i], stdNumTZ, layout[i+5:]
190
+ }
191
+ if len(layout) >= i+6 && layout[i:i+6] == "-07:00" {
192
+ return layout[0:i], stdNumColonTZ, layout[i+6:]
193
+ }
194
+ if len(layout) >= i+3 && layout[i:i+3] == "-07" {
195
+ return layout[0:i], stdNumShortTZ, layout[i+3:]
196
+ }
197
+
198
+ case 'Z': // Z070000, Z07:00:00, Z0700, Z07:00,
199
+ if len(layout) >= i+7 && layout[i:i+7] == "Z070000" {
200
+ return layout[0:i], stdISO8601SecondsTZ, layout[i+7:]
201
+ }
202
+ if len(layout) >= i+9 && layout[i:i+9] == "Z07:00:00" {
203
+ return layout[0:i], stdISO8601ColonSecondsTZ, layout[i+9:]
204
+ }
205
+ if len(layout) >= i+5 && layout[i:i+5] == "Z0700" {
206
+ return layout[0:i], stdISO8601TZ, layout[i+5:]
207
+ }
208
+ if len(layout) >= i+6 && layout[i:i+6] == "Z07:00" {
209
+ return layout[0:i], stdISO8601ColonTZ, layout[i+6:]
210
+ }
211
+ if len(layout) >= i+3 && layout[i:i+3] == "Z07" {
212
+ return layout[0:i], stdISO8601ShortTZ, layout[i+3:]
213
+ }
214
+
215
+ case '.', ',': // ,000, or .000, or ,999, or .999 - repeated digits for fractional seconds.
216
+ if i+1 < len(layout) && (layout[i+1] == '0' || layout[i+1] == '9') {
217
+ ch := layout[i+1]
218
+ j := i + 1
219
+ for j < len(layout) && layout[j] == ch {
220
+ j++
221
+ }
222
+ // String of digits must end here - only fractional second if all digits.
223
+ if !isDigit(layout, j) {
224
+ code := stdFracSecond0
225
+ if layout[i+1] == '9' {
226
+ code = stdFracSecond9
227
+ }
228
+ std := stdFracSecond(code, j-(i+1), c)
229
+ return layout[0:i], std, layout[j:]
230
+ }
231
+ }
232
+ }
233
+ }
234
+ return layout, 0, ""
235
+ }
236
+
237
+ var shortMonthNames = []string{
238
+ "Jan",
239
+ "Feb",
240
+ "Mar",
241
+ "Apr",
242
+ "May",
243
+ "Jun",
244
+ "Jul",
245
+ "Aug",
246
+ "Sep",
247
+ "Oct",
248
+ "Nov",
249
+ "Dec",
250
+ }
251
+
252
+ // isDigit reports whether s[i] is in range and is a decimal digit.
253
+ func isDigit(s string, i int) bool {
254
+ if len(s) <= i {
255
+ return false
256
+ }
257
+ c := s[i]
258
+ return '0' <= c && c <= '9'
259
+ }
260
+
261
+ // getnum parses s[0:1] or s[0:2] (fixed forces s[0:2])
262
+ // as a decimal integer and returns the integer and the
263
+ // remainder of the string.
264
+ func getnum(s string, fixed bool) (int, string, error) {
265
+ if !isDigit(s, 0) {
266
+ return 0, s, errBad
267
+ }
268
+ if !isDigit(s, 1) {
269
+ if fixed {
270
+ return 0, s, errBad
271
+ }
272
+ return int(s[0] - '0'), s[1:], nil
273
+ }
274
+ return int(s[0]-'0')*10 + int(s[1]-'0'), s[2:], nil
275
+ }
276
+
277
+ // getnum3 parses s[0:1], s[0:2], or s[0:3] (fixed forces s[0:3])
278
+ // as a decimal integer and returns the integer and the remainder
279
+ // of the string.
280
+ func getnum3(s string, fixed bool) (int, string, error) {
281
+ var n, i int
282
+ for i = 0; i < 3 && isDigit(s, i); i++ {
283
+ n = n*10 + int(s[i]-'0')
284
+ }
285
+ if i == 0 || fixed && i != 3 {
286
+ return 0, s, errBad
287
+ }
288
+ return n, s[i:], nil
289
+ }
290
+
291
+ var errBad = errors.New("bad value for field") // not passed to the user
292
+
293
+ // stdFracSecond returns the std for a fractional second with n digits and the
294
+ // separator sep.
295
+ func stdFracSecond(code, n, c int) int {
296
+ // Use 0xfff to make the failure case even more absurd.
297
+ if c == '.' {
298
+ return code | ((n & 0xfff) << stdArgShift)
299
+ }
300
+ return code | ((n & 0xfff) << stdArgShift) | 1<<stdSeparatorShift
301
+ }
302
+
303
+ func digitsLen(std int) int {
304
+ return (std >> stdArgShift) & 0xfff
305
+ }
306
+
307
+ func separator(std int) byte {
308
+ if (std >> stdSeparatorShift) == 0 {
309
+ return '.'
310
+ }
311
+ return ','
312
+ }
313
+
314
+ // appendInt appends the decimal form of x to b and returns the result.
315
+ // If the decimal form (excluding sign) is shorter than width, the result is padded with leading 0's.
316
+ // If x is negative, a leading '-' is added to the sign.
317
+ func appendInt(b []byte, x int, width int) []byte {
318
+ u := uint(x)
319
+ if x < 0 {
320
+ b = append(b, '-')
321
+ u = uint(-x)
322
+ }
323
+
324
+ // 2-digit and 4-digit fields are the most common in time formats.
325
+ utod := func(u uint) byte { return '0' + byte(u) }
326
+ switch {
327
+ case width == 2 && u < 100:
328
+ return append(b, utod(u/10), utod(u%10))
329
+ case width == 4 && u < 10000:
330
+ return append(b, utod(u/1000), utod(u/100%10), utod(u/10%10), utod(u%10))
331
+ }
332
+
333
+ // Compute the number of decimal digits.
334
+ var n int
335
+ if u == 0 {
336
+ n = 1
337
+ }
338
+ for u2 := u; u2 > 0; u2 = u2 / 10 {
339
+ n++
340
+ }
341
+
342
+ // Add 0-padding.
343
+ for pad := width - n; pad > 0; pad-- {
344
+ b = append(b, '0')
345
+ }
346
+
347
+ // Assemble the decimal in reverse order after the padding.
348
+ start := len(b)
349
+ b = append(b, make([]byte, n)...)
350
+ i := len(b) - 1
351
+ for u >= 10 && i > start {
352
+ q := u / 10
353
+ b[i] = utod(u - q*10)
354
+ u = q
355
+ i--
356
+ }
357
+ b[i] = utod(u)
358
+ return b
359
+ }
360
+
361
+ // formatNano appends a fractional second, as nanoseconds, to b
362
+ // and returns the result. The nanosec must be within [0, 999999999].
363
+ func formatNano(b []byte, nanosec uint, std int) []byte {
364
+ var (
365
+ n = digitsLen(std)
366
+ separator = separator(std)
367
+ trim = std&stdMask == stdFracSecond9
368
+ )
369
+ u := nanosec
370
+ var buf [9]byte
371
+ for start := len(buf); start > 0; {
372
+ start--
373
+ buf[start] = byte(u%10 + '0')
374
+ u /= 10
375
+ }
376
+
377
+ if n > 9 {
378
+ n = 9
379
+ }
380
+ if trim {
381
+ for n > 0 && buf[n-1] == '0' {
382
+ n--
383
+ }
384
+ if n == 0 {
385
+ return b
386
+ }
387
+ }
388
+ b = append(b, separator)
389
+ return append(b, buf[:n]...)
390
+ }
391
+
392
+ // String returns the time formatted using the format string
393
+ //
394
+ // "2006-01-02 15:04:05.999999999 -0700 MST"
395
+ func (t Time) String() string {
396
+ return t.Format("2006-01-02 15:04:05.999999999 -0700 MST")
397
+ }
398
+
399
+ // GoString implements fmt.GoStringer and formats t to be printed in Go source
400
+ // code.
401
+ func (t Time) GoString() string {
402
+ abs := t.abs()
403
+ year, month, day, _ := absDate(abs)
404
+ hour, min, sec := t.Clock()
405
+
406
+ buf := make([]byte, 0, len("time.Date(9999, time.September, 31, 23, 59, 59, 999999999, time.Local)"))
407
+ buf = append(buf, "time.Date("...)
408
+ buf = appendInt(buf, year, 0)
409
+ if January <= month && month <= December {
410
+ buf = append(buf, ", time."...)
411
+ buf = append(buf, longMonthNames[month-1]...)
412
+ } else {
413
+ // It's difficult to construct a time.Time with a date outside the
414
+ // standard range but we might as well try to handle the case.
415
+ buf = appendInt(buf, int(month), 0)
416
+ }
417
+ buf = append(buf, ", "...)
418
+ buf = appendInt(buf, day, 0)
419
+ buf = append(buf, ", "...)
420
+ buf = appendInt(buf, hour, 0)
421
+ buf = append(buf, ", "...)
422
+ buf = appendInt(buf, min, 0)
423
+ buf = append(buf, ", "...)
424
+ buf = appendInt(buf, sec, 0)
425
+ buf = append(buf, ", "...)
426
+ buf = appendInt(buf, t.Nanosecond(), 0)
427
+ buf = append(buf, ", "...)
428
+ switch loc := t.Location(); loc {
429
+ case UTC:
430
+ buf = append(buf, "time.UTC"...)
431
+ case Local:
432
+ buf = append(buf, "time.Local"...)
433
+ default:
434
+ // there are several options for how we could display this, none of
435
+ // which are great:
436
+ //
437
+ // - use Location(loc.name), which is not technically valid syntax
438
+ // - use LoadLocation(loc.name), which will cause a syntax error when
439
+ // embedded and also would require us to escape the string without
440
+ // importing fmt or strconv
441
+ // - try to use FixedZone, which would also require escaping the name
442
+ // and would represent e.g. "America/Los_Angeles" daylight saving time
443
+ // shifts inaccurately
444
+ // - use the pointer format, which is no worse than you'd get with the
445
+ // old fmt.Sprintf("%#v", t) format.
446
+ //
447
+ // Of these, Location(loc.name) is the least disruptive. This is an edge
448
+ // case we hope not to hit too often.
449
+ buf = append(buf, `time.Location(`...)
450
+ buf = append(buf, quote(loc.name)...)
451
+ buf = append(buf, ')')
452
+ }
453
+ buf = append(buf, ')')
454
+ return string(buf)
455
+ }
456
+
457
+ // Format returns a textual representation of the time value formatted according
458
+ // to the layout defined by the argument. See the documentation for the
459
+ // constant called Layout to see how to represent the layout format.
460
+ func (t Time) Format(layout string) string {
461
+ const bufSize = 64
462
+ var b []byte
463
+ max := len(layout) + 10
464
+ if max < bufSize {
465
+ b = make([]byte, 0, bufSize)
466
+ } else {
467
+ b = make([]byte, 0, max)
468
+ }
469
+ b = t.AppendFormat(b, layout)
470
+ return string(b)
471
+ }
472
+
473
+ // AppendFormat is like Format but appends the textual
474
+ // representation to b and returns the extended buffer.
475
+ func (t Time) AppendFormat(b []byte, layout string) []byte {
476
+ name, offset := t.zone()
477
+ abs := t.abs()
478
+ return t.appendFormat(b, layout, name, offset, abs)
479
+ }
480
+
481
+ func (t Time) appendFormat(b []byte, layout string, name string, offset int, abs int64) []byte {
482
+ var (
483
+ year int = -1
484
+ month Month
485
+ day int
486
+ yday int
487
+ hour int = -1
488
+ min int
489
+ sec int
490
+ )
491
+
492
+ // Each iteration generates one std value.
493
+ for layout != "" {
494
+ prefix, std, suffix := nextStdChunk(layout)
495
+ if prefix != "" {
496
+ b = append(b, prefix...)
497
+ }
498
+ if std == 0 {
499
+ break
500
+ }
501
+ layout = suffix
502
+
503
+ // Compute year, month, day if needed.
504
+ if year < 0 && std&stdNeedDate != 0 {
505
+ year, month, day, yday = absDate(abs)
506
+ yday++
507
+ }
508
+
509
+ // Compute hour, minute, second if needed.
510
+ if hour < 0 && std&stdNeedClock != 0 {
511
+ s := int(abs - floorDiv(abs, secondsPerDay)*secondsPerDay)
512
+ hour = s / secondsPerHour
513
+ s -= hour * secondsPerHour
514
+ min = s / secondsPerMinute
515
+ sec = s - min*secondsPerMinute
516
+ }
517
+
518
+ switch std & stdMask {
519
+ case stdYear:
520
+ y := year
521
+ if y < 0 {
522
+ y = -y
523
+ }
524
+ b = appendInt(b, y%100, 2)
525
+ case stdLongYear:
526
+ b = appendInt(b, year, 4)
527
+ case stdMonth:
528
+ b = append(b, shortMonthNames[month-1]...)
529
+ case stdLongMonth:
530
+ m := month.String()
531
+ b = append(b, m...)
532
+ case stdNumMonth:
533
+ b = appendInt(b, int(month), 0)
534
+ case stdZeroMonth:
535
+ b = appendInt(b, int(month), 2)
536
+ case stdWeekDay:
537
+ b = append(b, shortDayNames[absWeekday(abs)]...)
538
+ case stdLongWeekDay:
539
+ s := absWeekday(abs).String()
540
+ b = append(b, s...)
541
+ case stdDay:
542
+ b = appendInt(b, day, 0)
543
+ case stdUnderDay:
544
+ if day < 10 {
545
+ b = append(b, ' ')
546
+ }
547
+ b = appendInt(b, day, 0)
548
+ case stdZeroDay:
549
+ b = appendInt(b, day, 2)
550
+ case stdUnderYearDay:
551
+ if yday < 100 {
552
+ b = append(b, ' ')
553
+ if yday < 10 {
554
+ b = append(b, ' ')
555
+ }
556
+ }
557
+ b = appendInt(b, yday, 0)
558
+ case stdZeroYearDay:
559
+ b = appendInt(b, yday, 3)
560
+ case stdHour:
561
+ b = appendInt(b, hour, 2)
562
+ case stdHour12:
563
+ // Noon is 12PM, midnight is 12AM.
564
+ hr := hour % 12
565
+ if hr == 0 {
566
+ hr = 12
567
+ }
568
+ b = appendInt(b, hr, 0)
569
+ case stdZeroHour12:
570
+ // Noon is 12PM, midnight is 12AM.
571
+ hr := hour % 12
572
+ if hr == 0 {
573
+ hr = 12
574
+ }
575
+ b = appendInt(b, hr, 2)
576
+ case stdMinute:
577
+ b = appendInt(b, min, 0)
578
+ case stdZeroMinute:
579
+ b = appendInt(b, min, 2)
580
+ case stdSecond:
581
+ b = appendInt(b, sec, 0)
582
+ case stdZeroSecond:
583
+ b = appendInt(b, sec, 2)
584
+ case stdPM:
585
+ if hour >= 12 {
586
+ b = append(b, "PM"...)
587
+ } else {
588
+ b = append(b, "AM"...)
589
+ }
590
+ case stdpm:
591
+ if hour >= 12 {
592
+ b = append(b, "pm"...)
593
+ } else {
594
+ b = append(b, "am"...)
595
+ }
596
+ case stdISO8601TZ, stdISO8601ColonTZ, stdISO8601SecondsTZ, stdISO8601ShortTZ, stdISO8601ColonSecondsTZ, stdNumTZ, stdNumColonTZ, stdNumSecondsTz, stdNumShortTZ, stdNumColonSecondsTZ:
597
+ // Ugly special case. We cheat and take the "Z" variants
598
+ // to mean "the time zone as formatted for ISO 8601".
599
+ if offset == 0 && (std == stdISO8601TZ || std == stdISO8601ColonTZ || std == stdISO8601SecondsTZ || std == stdISO8601ShortTZ || std == stdISO8601ColonSecondsTZ) {
600
+ b = append(b, 'Z')
601
+ break
602
+ }
603
+ zone := offset / 60 // convert to minutes
604
+ absoffset := offset
605
+ if zone < 0 {
606
+ b = append(b, '-')
607
+ zone = -zone
608
+ absoffset = -absoffset
609
+ } else {
610
+ b = append(b, '+')
611
+ }
612
+ b = appendInt(b, zone/60, 2)
613
+ if std == stdISO8601ColonTZ || std == stdNumColonTZ || std == stdISO8601ColonSecondsTZ || std == stdNumColonSecondsTZ {
614
+ b = append(b, ':')
615
+ }
616
+ if std != stdNumShortTZ && std != stdISO8601ShortTZ {
617
+ b = appendInt(b, zone%60, 2)
618
+ }
619
+
620
+ // append seconds if appropriate
621
+ if std == stdISO8601SecondsTZ || std == stdNumSecondsTz || std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
622
+ if std == stdNumColonSecondsTZ || std == stdISO8601ColonSecondsTZ {
623
+ b = append(b, ':')
624
+ }
625
+ b = appendInt(b, absoffset%60, 2)
626
+ }
627
+
628
+ case stdTZ:
629
+ // Ugly special case. We cheat and take the "MST" variant
630
+ // to mean "the time zone abbreviation".
631
+ if name != "" {
632
+ b = append(b, name...)
633
+ break
634
+ }
635
+ // No time zone known for this time, but we must print one.
636
+ // Use the -0700 format.
637
+ zone := offset / 60 // convert to minutes
638
+ if zone < 0 {
639
+ b = append(b, '-')
640
+ zone = -zone
641
+ } else {
642
+ b = append(b, '+')
643
+ }
644
+ b = appendInt(b, zone/60, 2)
645
+ b = appendInt(b, zone%60, 2)
646
+ case stdFracSecond0, stdFracSecond9:
647
+ b = formatNano(b, uint(t.nsec), std)
648
+ }
649
+ }
650
+ return b
651
+ }
652
+
653
+ var errAppendBadYear = errors.New("year outside of range [0,9999]")
654
+ var errAppendBadZone = errors.New("timezone hour outside of range [0,23]")
655
+
656
+ // appendStrictRFC3339 formats t as RFC 3339, rejecting what that format can
657
+ // not represent.
658
+ func (t Time) appendStrictRFC3339(b []byte) ([]byte, error) {
659
+ if y := t.Year(); y < 0 || y >= 10000 {
660
+ return b, errAppendBadYear
661
+ }
662
+ _, offset := t.zone()
663
+ if offset <= -24*3600 || offset >= 24*3600 {
664
+ return b, errAppendBadZone
665
+ }
666
+ b = t.AppendFormat(b, RFC3339Nano)
667
+ return b, nil
668
+ }
669
+
670
+ // MarshalJSON implements the encoding/json.Marshaler interface. The time is a
671
+ // quoted string in the RFC 3339 format with sub-second precision. If the
672
+ // timestamp cannot be represented as valid RFC 3339 (e.g., the year is out of
673
+ // range), then an error is reported.
674
+ func (t Time) MarshalJSON() ([]byte, error) {
675
+ b := make([]byte, 0, len(RFC3339Nano)+len(`""`))
676
+ b = append(b, '"')
677
+ b, err := t.appendStrictRFC3339(b)
678
+ b = append(b, '"')
679
+ if err != nil {
680
+ return nil, errors.New("Time.MarshalJSON: " + err.Error())
681
+ }
682
+ return b, nil
683
+ }
684
+
685
+ // UnmarshalJSON implements the encoding/json.Unmarshaler interface. The time
686
+ // must be a quoted string in the RFC 3339 format.
687
+ func (t *Time) UnmarshalJSON(data []byte) error {
688
+ if string(data) == "null" {
689
+ return nil
690
+ }
691
+ if len(data) < 2 || data[0] != '"' || data[len(data)-1] != '"' {
692
+ return errors.New("Time.UnmarshalJSON: input is not a JSON string")
693
+ }
694
+ data = data[len(`"`) : len(data)-len(`"`)]
695
+ parsed, err := parseStrictRFC3339(data)
696
+ *t = parsed
697
+ return err
698
+ }
699
+
700
+ // MarshalText implements the encoding.TextMarshaler interface. The time is
701
+ // formatted in RFC 3339 format with sub-second precision. If the timestamp
702
+ // cannot be represented as valid RFC 3339 (e.g., the year is out of range),
703
+ // then an error is returned.
704
+ func (t Time) MarshalText() ([]byte, error) {
705
+ b := make([]byte, 0, len(RFC3339Nano))
706
+ b, err := t.appendStrictRFC3339(b)
707
+ if err != nil {
708
+ return nil, errors.New("Time.MarshalText: " + err.Error())
709
+ }
710
+ return b, nil
711
+ }
712
+
713
+ // UnmarshalText implements the encoding.TextUnmarshaler interface. The time
714
+ // must be in the RFC 3339 format.
715
+ func (t *Time) UnmarshalText(data []byte) error {
716
+ parsed, err := parseStrictRFC3339(data)
717
+ *t = parsed
718
+ return err
719
+ }
720
+
721
+ func parseStrictRFC3339(b []byte) (Time, error) {
722
+ t, err := Parse(RFC3339, string(b))
723
+ if err != nil {
724
+ return Time{}, err
725
+ }
726
+
727
+ // The parse template syntax cannot correctly validate RFC 3339.
728
+ // Explicitly check for cases that Parse is unable to validate for.
729
+ // See https://go.dev/issue/54580.
730
+ num2 := func(b []byte) byte { return 10*(b[0]-'0') + (b[1] - '0') }
731
+ switch {
732
+ case b[len("2006-01-02T")+1] == ':': // hour must be two digits
733
+ return Time{}, &ParseError{RFC3339, string(b), "15", string(b[len("2006-01-02T"):][:1]), ""}
734
+ case b[len("2006-01-02T15:04:05")] == ',': // sub-second separator must be a period
735
+ return Time{}, &ParseError{RFC3339, string(b), ".", ",", ""}
736
+ case b[len(b)-1] != 'Z':
737
+ switch {
738
+ case num2(b[len(b)-len("07:00"):]) >= 24: // timezone hour must be in range
739
+ return Time{}, &ParseError{RFC3339, string(b), "Z07:00", string(b[len(b)-len("Z07:00"):]), ": timezone hour out of range"}
740
+ case num2(b[len(b)-len("00"):]) >= 60: // timezone minute must be in range
741
+ return Time{}, &ParseError{RFC3339, string(b), "minute", string(b[len(b)-len("00"):]), ""}
742
+ }
743
+ }
744
+ return t, nil
745
+ }