ics - params.go
1 package ics
2
3 // File automatically generated with ./genParams.sh
4
5 import (
6 "errors"
7 "fmt"
8 "regexp"
9 "strings"
10 "unicode/utf8"
11
12 "vimagination.zapto.org/parser"
13 )
14
15 // AlternativeRepresentation is an alternate text representation for the
16 // property value
17 type ParamAlternativeRepresentation URI
18
19 func (t *ParamAlternativeRepresentation) decode(vs []parser.Token) error {
20 if len(vs) != 1 {
21 return fmt.Errorf(errDecodingType, cAlternativeRepresentation, ErrInvalidParam)
22 }
23 if vs[0].Type != tokenParamQuotedValue {
24 return fmt.Errorf(errDecodingType, cAlternativeRepresentation, ErrInvalidParam)
25 }
26 var q URI
27 if err := q.decode(nil, vs[0].Data); err != nil {
28 return fmt.Errorf(errDecodingType, cAlternativeRepresentation, err)
29 }
30 *t = ParamAlternativeRepresentation(q)
31 return nil
32 }
33
34 func (t ParamAlternativeRepresentation) encode(w writer) {
35 if len(t.String()) == 0 {
36 return
37 }
38 w.WriteString(";ALTREP=")
39 q := URI(t)
40 q.encode(w)
41 }
42
43 func (t ParamAlternativeRepresentation) valid() error {
44 q := URI(t)
45 if err := q.valid(); err != nil {
46 return fmt.Errorf(errValidatingType, cAlternativeRepresentation, err)
47 }
48 return nil
49 }
50
51 // CommonName is the common name to be associated with the calendar user
52 // specified by the property
53 type ParamCommonName string
54
55 // NewCommonName returns a *ParamCommonName for ease of use with optional values
56 func NewCommonName(v ParamCommonName) *ParamCommonName {
57 return &v
58 }
59
60 func (t *ParamCommonName) decode(vs []parser.Token) error {
61 if len(vs) != 1 {
62 return fmt.Errorf(errDecodingType, cCommonName, ErrInvalidParam)
63 }
64 *t = ParamCommonName(decode6868(vs[0].Data))
65 return nil
66 }
67
68 func (t ParamCommonName) encode(w writer) {
69 if len(t) == 0 {
70 return
71 }
72 w.WriteString(";CN=")
73 if strings.ContainsAny(string(t), nonsafeChars[32:]) {
74 w.WriteString("\"")
75 w.Write(encode6868(string(t)))
76 w.WriteString("\"")
77 } else {
78 w.Write(encode6868(string(t)))
79 }
80 }
81
82 func (t ParamCommonName) valid() error {
83 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
84 return fmt.Errorf(errValidatingType, cCommonName, ErrInvalidText)
85 }
86 return nil
87 }
88
89 // CalendarUserType is identify the type of calendar user specified by the
90 // property
91 type ParamCalendarUserType uint8
92
93 // CalendarUserType constant values
94 const (
95 CalendarUserTypeUnknown ParamCalendarUserType = iota
96 CalendarUserTypeIndividual
97 CalendarUserTypeGroup
98 CalendarUserTypeResource
99 CalendarUserTypeRoom
100 )
101
102 // New returns a pointer to the type (used with constants for ease of use with
103 // optional values)
104 func (t ParamCalendarUserType) New() *ParamCalendarUserType {
105 return &t
106 }
107
108 func (t *ParamCalendarUserType) decode(vs []parser.Token) error {
109 if len(vs) != 1 {
110 return fmt.Errorf(errDecodingType, cCalendarUserType, ErrInvalidParam)
111 }
112 switch strings.ToUpper(vs[0].Data) {
113 case "INDIVIDUAL":
114 *t = CalendarUserTypeIndividual
115 case "GROUP":
116 *t = CalendarUserTypeGroup
117 case "RESOURCE":
118 *t = CalendarUserTypeResource
119 case "ROOM":
120 *t = CalendarUserTypeRoom
121 default:
122 *t = CalendarUserTypeUnknown
123 }
124 return nil
125 }
126
127 func (t ParamCalendarUserType) encode(w writer) {
128 w.WriteString(";CUTYPE=")
129 switch t {
130 case CalendarUserTypeIndividual:
131 w.WriteString("INDIVIDUAL")
132 case CalendarUserTypeGroup:
133 w.WriteString("GROUP")
134 case CalendarUserTypeResource:
135 w.WriteString("RESOURCE")
136 case CalendarUserTypeRoom:
137 w.WriteString("ROOM")
138 default:
139 w.WriteString("UNKNOWN")
140 }
141 }
142
143 func (t ParamCalendarUserType) valid() error {
144 return nil
145 }
146
147 // Delegator is used to specify the calendar users that have delegated their
148 // participation to the calendar user specified by the property
149 type ParamDelegator []CalendarAddress
150
151 func (t *ParamDelegator) decode(vs []parser.Token) error {
152 for _, v := range vs {
153 if v.Type != tokenParamQuotedValue {
154 return fmt.Errorf(errDecodingType, cDelegator, ErrInvalidParam)
155 }
156 var q CalendarAddress
157 if err := q.decode(nil, v.Data); err != nil {
158 return fmt.Errorf(errDecodingType, cDelegator, err)
159 }
160 *t = append(*t, q)
161 }
162 return nil
163 }
164
165 func (t ParamDelegator) encode(w writer) {
166 if len(t) == 0 {
167 return
168 }
169 w.WriteString(";DELEGATED-FROM=")
170 for n, v := range t {
171 if n > 0 {
172 w.WriteString(",")
173 }
174 q := CalendarAddress(v)
175 q.encode(w)
176 }
177 }
178
179 func (t ParamDelegator) valid() error {
180 for _, v := range t {
181 if err := v.valid(); err != nil {
182 return fmt.Errorf(errValidatingType, cDelegator, err)
183 }
184 }
185 return nil
186 }
187
188 // Delagatee is used to specify the calendar users to whom the calendar user
189 // specified by the property has delegated participation
190 type ParamDelagatee []CalendarAddress
191
192 func (t *ParamDelagatee) decode(vs []parser.Token) error {
193 for _, v := range vs {
194 if v.Type != tokenParamQuotedValue {
195 return fmt.Errorf(errDecodingType, cDelagatee, ErrInvalidParam)
196 }
197 var q CalendarAddress
198 if err := q.decode(nil, v.Data); err != nil {
199 return fmt.Errorf(errDecodingType, cDelagatee, err)
200 }
201 *t = append(*t, q)
202 }
203 return nil
204 }
205
206 func (t ParamDelagatee) encode(w writer) {
207 if len(t) == 0 {
208 return
209 }
210 w.WriteString(";DELEGATED-TO=")
211 for n, v := range t {
212 if n > 0 {
213 w.WriteString(",")
214 }
215 q := CalendarAddress(v)
216 q.encode(w)
217 }
218 }
219
220 func (t ParamDelagatee) valid() error {
221 for _, v := range t {
222 if err := v.valid(); err != nil {
223 return fmt.Errorf(errValidatingType, cDelagatee, err)
224 }
225 }
226 return nil
227 }
228
229 // DirectoryEntry is a reference to a directory entry associated with the
230 // calendar
231 type ParamDirectoryEntry string
232
233 // NewDirectoryEntry returns a *ParamDirectoryEntry for ease of use with optional values
234 func NewDirectoryEntry(v ParamDirectoryEntry) *ParamDirectoryEntry {
235 return &v
236 }
237
238 func (t *ParamDirectoryEntry) decode(vs []parser.Token) error {
239 if len(vs) != 1 {
240 return fmt.Errorf(errDecodingType, cDirectoryEntry, ErrInvalidParam)
241 }
242 if vs[0].Type != tokenParamQuotedValue {
243 return fmt.Errorf(errDecodingType, cDirectoryEntry, ErrInvalidParam)
244 }
245 *t = ParamDirectoryEntry(decode6868(vs[0].Data))
246 return nil
247 }
248
249 func (t ParamDirectoryEntry) encode(w writer) {
250 if len(t) == 0 {
251 return
252 }
253 w.WriteString(";DIR=")
254 w.WriteString("\"")
255 w.Write(encode6868(string(t)))
256 w.WriteString("\"")
257 }
258
259 func (t ParamDirectoryEntry) valid() error {
260 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
261 return fmt.Errorf(errValidatingType, cDirectoryEntry, ErrInvalidText)
262 }
263 return nil
264 }
265
266 // Encoding is the inline encoding for the property value
267 type ParamEncoding uint8
268
269 // Encoding constant values
270 const (
271 Encoding8bit ParamEncoding = iota
272 EncodingBase64
273 )
274
275 // New returns a pointer to the type (used with constants for ease of use with
276 // optional values)
277 func (t ParamEncoding) New() *ParamEncoding {
278 return &t
279 }
280
281 func (t *ParamEncoding) decode(vs []parser.Token) error {
282 if len(vs) != 1 {
283 return fmt.Errorf(errDecodingType, cEncoding, ErrInvalidParam)
284 }
285 switch strings.ToUpper(vs[0].Data) {
286 case "8BIT":
287 *t = Encoding8bit
288 case "BASE64":
289 *t = EncodingBase64
290 default:
291 return fmt.Errorf(errDecodingType, cEncoding, ErrInvalidParam)
292 }
293 return nil
294 }
295
296 func (t ParamEncoding) encode(w writer) {
297 w.WriteString(";ENCODING=")
298 switch t {
299 case Encoding8bit:
300 w.WriteString("8BIT")
301 case EncodingBase64:
302 w.WriteString("BASE64")
303 }
304 }
305
306 func (t ParamEncoding) valid() error {
307 switch t {
308 case Encoding8bit, EncodingBase64:
309 default:
310 return fmt.Errorf(errValidatingType, cEncoding, ErrInvalidValue)
311 }
312 return nil
313 }
314
315 // FormatType is the content type of a referenced object
316 type ParamFormatType string
317
318 // NewFormatType returns a *ParamFormatType for ease of use with optional values
319 func NewFormatType(v ParamFormatType) *ParamFormatType {
320 return &v
321 }
322
323 var regexFormatType *regexp.Regexp
324
325 func (t *ParamFormatType) decode(vs []parser.Token) error {
326 if len(vs) != 1 {
327 return fmt.Errorf(errDecodingType, cFormatType, ErrInvalidParam)
328 }
329 if !regexFormatType.MatchString(vs[0].Data) {
330 return fmt.Errorf(errDecodingType, cFormatType, ErrInvalidParam)
331 }
332 *t = ParamFormatType(vs[0].Data)
333 return nil
334 }
335
336 func (t ParamFormatType) encode(w writer) {
337 if len(t) == 0 {
338 return
339 }
340 w.WriteString(";FMTTYPE=")
341 if strings.ContainsAny(string(t), nonsafeChars[32:]) {
342 w.WriteString("\"")
343 w.Write(encode6868(string(t)))
344 w.WriteString("\"")
345 } else {
346 w.Write(encode6868(string(t)))
347 }
348 }
349
350 func (t ParamFormatType) valid() error {
351 if !regexFormatType.Match([]byte(t)) {
352 return fmt.Errorf(errValidatingType, cFormatType, ErrInvalidValue)
353 }
354 return nil
355 }
356
357 // FreeBusyType is used to specify the free or busy time type
358 type ParamFreeBusyType uint8
359
360 // FreeBusyType constant values
361 const (
362 FreeBusyTypeUnknown ParamFreeBusyType = iota
363 FreeBusyTypeFree
364 FreeBusyTypeBusy
365 FreeBusyTypeBusyUnavailable
366 FreeBusyTypeBusyTentative
367 )
368
369 // New returns a pointer to the type (used with constants for ease of use with
370 // optional values)
371 func (t ParamFreeBusyType) New() *ParamFreeBusyType {
372 return &t
373 }
374
375 func (t *ParamFreeBusyType) decode(vs []parser.Token) error {
376 if len(vs) != 1 {
377 return fmt.Errorf(errDecodingType, cFreeBusyType, ErrInvalidParam)
378 }
379 switch strings.ToUpper(vs[0].Data) {
380 case "FREE":
381 *t = FreeBusyTypeFree
382 case "BUSY":
383 *t = FreeBusyTypeBusy
384 case "BUSY-UNAVAILABLE":
385 *t = FreeBusyTypeBusyUnavailable
386 case "BUSY-TENTATIVE":
387 *t = FreeBusyTypeBusyTentative
388 default:
389 *t = FreeBusyTypeUnknown
390 }
391 return nil
392 }
393
394 func (t ParamFreeBusyType) encode(w writer) {
395 w.WriteString(";FBTYPE=")
396 switch t {
397 case FreeBusyTypeFree:
398 w.WriteString("FREE")
399 case FreeBusyTypeBusy:
400 w.WriteString("BUSY")
401 case FreeBusyTypeBusyUnavailable:
402 w.WriteString("BUSY-UNAVAILABLE")
403 case FreeBusyTypeBusyTentative:
404 w.WriteString("BUSY-TENTATIVE")
405 default:
406 w.WriteString("UNKNOWN")
407 }
408 }
409
410 func (t ParamFreeBusyType) valid() error {
411 return nil
412 }
413
414 // Language is the language for text values
415 type ParamLanguage string
416
417 // NewLanguage returns a *ParamLanguage for ease of use with optional values
418 func NewLanguage(v ParamLanguage) *ParamLanguage {
419 return &v
420 }
421
422 func (t *ParamLanguage) decode(vs []parser.Token) error {
423 if len(vs) != 1 {
424 return fmt.Errorf(errDecodingType, cLanguage, ErrInvalidParam)
425 }
426 *t = ParamLanguage(decode6868(vs[0].Data))
427 return nil
428 }
429
430 func (t ParamLanguage) encode(w writer) {
431 if len(t) == 0 {
432 return
433 }
434 w.WriteString(";LANGUAGE=")
435 if strings.ContainsAny(string(t), nonsafeChars[32:]) {
436 w.WriteString("\"")
437 w.Write(encode6868(string(t)))
438 w.WriteString("\"")
439 } else {
440 w.Write(encode6868(string(t)))
441 }
442 }
443
444 func (t ParamLanguage) valid() error {
445 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
446 return fmt.Errorf(errValidatingType, cLanguage, ErrInvalidText)
447 }
448 return nil
449 }
450
451 // Member is used to specify the group or list membership of the calendar
452 type ParamMember []string
453
454 // NewMember returns a *ParamMember for ease of use with optional values
455 func NewMember(v ParamMember) *ParamMember {
456 return &v
457 }
458
459 func (t *ParamMember) decode(vs []parser.Token) error {
460 for _, v := range vs {
461 if v.Type != tokenParamQuotedValue {
462 return fmt.Errorf(errDecodingType, cMember, ErrInvalidParam)
463 }
464 *t = append(*t, decode6868(v.Data))
465 }
466 return nil
467 }
468
469 func (t ParamMember) encode(w writer) {
470 if len(t) == 0 {
471 return
472 }
473 w.WriteString(";MEMBER=")
474 for n, v := range t {
475 if n > 0 {
476 w.WriteString(",")
477 }
478 w.WriteString("\"")
479 w.Write(encode6868(string(v)))
480 w.WriteString("\"")
481 }
482 }
483
484 func (t ParamMember) valid() error {
485 for _, v := range t {
486 if strings.ContainsAny(string(v), nonsafeChars[:31]) {
487 return fmt.Errorf(errValidatingType, cMember, ErrInvalidText)
488 }
489 }
490 return nil
491 }
492
493 // ParticipationStatus is used to specify the participation status for the
494 // calendar
495 type ParamParticipationStatus uint8
496
497 // ParticipationStatus constant values
498 const (
499 ParticipationStatusUnknown ParamParticipationStatus = iota
500 ParticipationStatusNeedsAction
501 ParticipationStatusAccepted
502 ParticipationStatusDeclined
503 ParticipationStatusTentative
504 ParticipationStatusDelegated
505 ParticipationStatusCompleted
506 ParticipationStatusInProcess
507 )
508
509 // New returns a pointer to the type (used with constants for ease of use with
510 // optional values)
511 func (t ParamParticipationStatus) New() *ParamParticipationStatus {
512 return &t
513 }
514
515 func (t *ParamParticipationStatus) decode(vs []parser.Token) error {
516 if len(vs) != 1 {
517 return fmt.Errorf(errDecodingType, cParticipationStatus, ErrInvalidParam)
518 }
519 switch strings.ToUpper(vs[0].Data) {
520 case "NEEDS-ACTION":
521 *t = ParticipationStatusNeedsAction
522 case "ACCEPTED":
523 *t = ParticipationStatusAccepted
524 case "DECLINED":
525 *t = ParticipationStatusDeclined
526 case "TENTATIVE":
527 *t = ParticipationStatusTentative
528 case "DELEGATED":
529 *t = ParticipationStatusDelegated
530 case "COMPLETED":
531 *t = ParticipationStatusCompleted
532 case "IN-PROCESS":
533 *t = ParticipationStatusInProcess
534 default:
535 *t = ParticipationStatusUnknown
536 }
537 return nil
538 }
539
540 func (t ParamParticipationStatus) encode(w writer) {
541 w.WriteString(";PARTSTAT=")
542 switch t {
543 case ParticipationStatusNeedsAction:
544 w.WriteString("NEEDS-ACTION")
545 case ParticipationStatusAccepted:
546 w.WriteString("ACCEPTED")
547 case ParticipationStatusDeclined:
548 w.WriteString("DECLINED")
549 case ParticipationStatusTentative:
550 w.WriteString("TENTATIVE")
551 case ParticipationStatusDelegated:
552 w.WriteString("DELEGATED")
553 case ParticipationStatusCompleted:
554 w.WriteString("COMPLETED")
555 case ParticipationStatusInProcess:
556 w.WriteString("IN-PROCESS")
557 default:
558 w.WriteString("UNKNOWN")
559 }
560 }
561
562 func (t ParamParticipationStatus) valid() error {
563 return nil
564 }
565
566 // Range is used to specify the effective range of recurrence instances from the
567 // instance specified by the recurrence identifier specified by the property
568 type ParamRange struct{}
569
570 func (t *ParamRange) decode(vs []parser.Token) error {
571 if len(vs) != 1 {
572 return fmt.Errorf(errDecodingType, cRange, ErrInvalidParam)
573 }
574 if strings.ToUpper(vs[0].Data) != "THISANDFUTURE" {
575 return fmt.Errorf(errDecodingType, cRange, ErrInvalidParam)
576 }
577 return nil
578 }
579
580 func (t ParamRange) encode(w writer) {
581 w.WriteString(";RANGE=")
582 w.WriteString("THISANDFUTURE")
583 }
584
585 func (t ParamRange) valid() error {
586 return nil
587 }
588
589 // Related is the relationship of the alarm trigger with respect to the start or
590 // end of the calendar component
591 type ParamRelated uint8
592
593 // Related constant values
594 const (
595 RelatedStart ParamRelated = iota
596 RelatedEnd
597 )
598
599 // New returns a pointer to the type (used with constants for ease of use with
600 // optional values)
601 func (t ParamRelated) New() *ParamRelated {
602 return &t
603 }
604
605 func (t *ParamRelated) decode(vs []parser.Token) error {
606 if len(vs) != 1 {
607 return fmt.Errorf(errDecodingType, cRelated, ErrInvalidParam)
608 }
609 switch strings.ToUpper(vs[0].Data) {
610 case "START":
611 *t = RelatedStart
612 case "END":
613 *t = RelatedEnd
614 default:
615 return fmt.Errorf(errDecodingType, cRelated, ErrInvalidParam)
616 }
617 return nil
618 }
619
620 func (t ParamRelated) encode(w writer) {
621 w.WriteString(";RELATED=")
622 switch t {
623 case RelatedStart:
624 w.WriteString("START")
625 case RelatedEnd:
626 w.WriteString("END")
627 }
628 }
629
630 func (t ParamRelated) valid() error {
631 switch t {
632 case RelatedStart, RelatedEnd:
633 default:
634 return fmt.Errorf(errValidatingType, cRelated, ErrInvalidValue)
635 }
636 return nil
637 }
638
639 // RelationshipType is the type of hierarchical relationship associated with the
640 // calendar component specified by the property
641 type ParamRelationshipType uint8
642
643 // RelationshipType constant values
644 const (
645 RelationshipTypeUnknown ParamRelationshipType = iota
646 RelationshipTypeParent
647 RelationshipTypeChild
648 RelationshipTypeSibling
649 )
650
651 // New returns a pointer to the type (used with constants for ease of use with
652 // optional values)
653 func (t ParamRelationshipType) New() *ParamRelationshipType {
654 return &t
655 }
656
657 func (t *ParamRelationshipType) decode(vs []parser.Token) error {
658 if len(vs) != 1 {
659 return fmt.Errorf(errDecodingType, cRelationshipType, ErrInvalidParam)
660 }
661 switch strings.ToUpper(vs[0].Data) {
662 case "PARENT":
663 *t = RelationshipTypeParent
664 case "CHILD":
665 *t = RelationshipTypeChild
666 case "SIBLING":
667 *t = RelationshipTypeSibling
668 default:
669 *t = RelationshipTypeUnknown
670 }
671 return nil
672 }
673
674 func (t ParamRelationshipType) encode(w writer) {
675 w.WriteString(";RELTYPE=")
676 switch t {
677 case RelationshipTypeParent:
678 w.WriteString("PARENT")
679 case RelationshipTypeChild:
680 w.WriteString("CHILD")
681 case RelationshipTypeSibling:
682 w.WriteString("SIBLING")
683 default:
684 w.WriteString("UNKNOWN")
685 }
686 }
687
688 func (t ParamRelationshipType) valid() error {
689 return nil
690 }
691
692 // ParticipationRole is used to specify the participation role for the calendar
693 // user specified by the property
694 type ParamParticipationRole uint8
695
696 // ParticipationRole constant values
697 const (
698 ParticipationRoleUnknown ParamParticipationRole = iota
699 ParticipationRoleRequiredParticipant
700 ParticipationRoleChair
701 ParticipationRoleOptParticipant
702 ParticipationRoleNonParticipant
703 )
704
705 // New returns a pointer to the type (used with constants for ease of use with
706 // optional values)
707 func (t ParamParticipationRole) New() *ParamParticipationRole {
708 return &t
709 }
710
711 func (t *ParamParticipationRole) decode(vs []parser.Token) error {
712 if len(vs) != 1 {
713 return fmt.Errorf(errDecodingType, cParticipationRole, ErrInvalidParam)
714 }
715 switch strings.ToUpper(vs[0].Data) {
716 case "REQ-PARTICIPANT":
717 *t = ParticipationRoleRequiredParticipant
718 case "CHAIR":
719 *t = ParticipationRoleChair
720 case "OPT-PARTICIPANT":
721 *t = ParticipationRoleOptParticipant
722 case "NON-PARTICIPANT":
723 *t = ParticipationRoleNonParticipant
724 default:
725 *t = ParticipationRoleUnknown
726 }
727 return nil
728 }
729
730 func (t ParamParticipationRole) encode(w writer) {
731 w.WriteString(";ROLE=")
732 switch t {
733 case ParticipationRoleRequiredParticipant:
734 w.WriteString("REQ-PARTICIPANT")
735 case ParticipationRoleChair:
736 w.WriteString("CHAIR")
737 case ParticipationRoleOptParticipant:
738 w.WriteString("OPT-PARTICIPANT")
739 case ParticipationRoleNonParticipant:
740 w.WriteString("NON-PARTICIPANT")
741 default:
742 w.WriteString("UNKNOWN")
743 }
744 }
745
746 func (t ParamParticipationRole) valid() error {
747 return nil
748 }
749
750 // RSVP is used to specify whether there is an expectation of a favor of a reply
751 // from the calendar user specified by the property value
752 type ParamRSVP Boolean
753
754 // NewRSVP returns a *ParamRSVP for ease of use with optional values
755 func NewRSVP(v ParamRSVP) *ParamRSVP {
756 return &v
757 }
758
759 func (t *ParamRSVP) decode(vs []parser.Token) error {
760 if len(vs) != 1 {
761 return fmt.Errorf(errDecodingType, cRSVP, ErrInvalidParam)
762 }
763 var q Boolean
764 if err := q.decode(nil, vs[0].Data); err != nil {
765 return fmt.Errorf(errDecodingType, cRSVP, err)
766 }
767 *t = ParamRSVP(q)
768 return nil
769 }
770
771 func (t ParamRSVP) encode(w writer) {
772 if !t {
773 return
774 }
775 w.WriteString(";RSVP=")
776 q := Boolean(t)
777 q.encode(w)
778 }
779
780 func (t ParamRSVP) valid() error {
781 return nil
782 }
783
784 // SentBy is used to specify the calendar user that is acting on behalf of the
785 // calendar user specified by the property
786 type ParamSentBy string
787
788 // NewSentBy returns a *ParamSentBy for ease of use with optional values
789 func NewSentBy(v ParamSentBy) *ParamSentBy {
790 return &v
791 }
792
793 func (t *ParamSentBy) decode(vs []parser.Token) error {
794 if len(vs) != 1 {
795 return fmt.Errorf(errDecodingType, cSentBy, ErrInvalidParam)
796 }
797 if vs[0].Type != tokenParamQuotedValue {
798 return fmt.Errorf(errDecodingType, cSentBy, ErrInvalidParam)
799 }
800 *t = ParamSentBy(decode6868(vs[0].Data))
801 return nil
802 }
803
804 func (t ParamSentBy) encode(w writer) {
805 if len(t) == 0 {
806 return
807 }
808 w.WriteString(";SENT-BY=")
809 w.WriteString("\"")
810 w.Write(encode6868(string(t)))
811 w.WriteString("\"")
812 }
813
814 func (t ParamSentBy) valid() error {
815 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
816 return fmt.Errorf(errValidatingType, cSentBy, ErrInvalidText)
817 }
818 return nil
819 }
820
821 // TimezoneID is used to specify the identifier for the time zone definition for
822 // a time component in the property value
823 type ParamTimezoneID string
824
825 // NewTimezoneID returns a *ParamTimezoneID for ease of use with optional values
826 func NewTimezoneID(v ParamTimezoneID) *ParamTimezoneID {
827 return &v
828 }
829
830 func (t *ParamTimezoneID) decode(vs []parser.Token) error {
831 if len(vs) != 1 {
832 return fmt.Errorf(errDecodingType, cTimezoneID, ErrInvalidParam)
833 }
834 *t = ParamTimezoneID(decode6868(vs[0].Data))
835 return nil
836 }
837
838 func (t ParamTimezoneID) encode(w writer) {
839 if len(t) == 0 {
840 return
841 }
842 w.WriteString(";TZID=")
843 if strings.ContainsAny(string(t), nonsafeChars[32:]) {
844 w.WriteString("\"")
845 w.Write(encode6868(string(t)))
846 w.WriteString("\"")
847 } else {
848 w.Write(encode6868(string(t)))
849 }
850 }
851
852 func (t ParamTimezoneID) valid() error {
853 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
854 return fmt.Errorf(errValidatingType, cTimezoneID, ErrInvalidText)
855 }
856 return nil
857 }
858
859 // Value is used to explicitly specify the value type format for a property
860 // value
861 type ParamValue uint8
862
863 // Value constant values
864 const (
865 ValueUnknown ParamValue = iota
866 ValueBinary
867 ValueBoolean
868 ValueCalendarAddress
869 ValueDate
870 ValueDateTime
871 ValueDuration
872 ValueFloat
873 ValueInteger
874 ValuePeriod
875 ValueRecur
876 ValueText
877 ValueTime
878 ValueURI
879 ValueUTCOffset
880 )
881
882 // New returns a pointer to the type (used with constants for ease of use with
883 // optional values)
884 func (t ParamValue) New() *ParamValue {
885 return &t
886 }
887
888 func (t *ParamValue) decode(vs []parser.Token) error {
889 if len(vs) != 1 {
890 return fmt.Errorf(errDecodingType, cValue, ErrInvalidParam)
891 }
892 switch strings.ToUpper(vs[0].Data) {
893 case "BINARY":
894 *t = ValueBinary
895 case "BOOLEAN":
896 *t = ValueBoolean
897 case "CAL-ADDRESS":
898 *t = ValueCalendarAddress
899 case "DATE":
900 *t = ValueDate
901 case "DATE-TIME":
902 *t = ValueDateTime
903 case "DURATION":
904 *t = ValueDuration
905 case "FLOAT":
906 *t = ValueFloat
907 case "INTEGER":
908 *t = ValueInteger
909 case "PERIOD":
910 *t = ValuePeriod
911 case "RECUR":
912 *t = ValueRecur
913 case "TEXT":
914 *t = ValueText
915 case "TIME":
916 *t = ValueTime
917 case "URI":
918 *t = ValueURI
919 case "UTC-OFFSET":
920 *t = ValueUTCOffset
921 default:
922 *t = ValueUnknown
923 }
924 return nil
925 }
926
927 func (t ParamValue) encode(w writer) {
928 w.WriteString(";VALUE=")
929 switch t {
930 case ValueBinary:
931 w.WriteString("BINARY")
932 case ValueBoolean:
933 w.WriteString("BOOLEAN")
934 case ValueCalendarAddress:
935 w.WriteString("CAL-ADDRESS")
936 case ValueDate:
937 w.WriteString("DATE")
938 case ValueDateTime:
939 w.WriteString("DATE-TIME")
940 case ValueDuration:
941 w.WriteString("DURATION")
942 case ValueFloat:
943 w.WriteString("FLOAT")
944 case ValueInteger:
945 w.WriteString("INTEGER")
946 case ValuePeriod:
947 w.WriteString("PERIOD")
948 case ValueRecur:
949 w.WriteString("RECUR")
950 case ValueText:
951 w.WriteString("TEXT")
952 case ValueTime:
953 w.WriteString("TIME")
954 case ValueURI:
955 w.WriteString("URI")
956 case ValueUTCOffset:
957 w.WriteString("UTC-OFFSET")
958 default:
959 w.WriteString("UNKNOWN")
960 }
961 }
962
963 func (t ParamValue) valid() error {
964 return nil
965 }
966
967 // URI
968 type ParamURI URI
969
970 func (t *ParamURI) decode(vs []parser.Token) error {
971 if len(vs) != 1 {
972 return fmt.Errorf(errDecodingType, cURI, ErrInvalidParam)
973 }
974 if vs[0].Type != tokenParamQuotedValue {
975 return fmt.Errorf(errDecodingType, cURI, ErrInvalidParam)
976 }
977 var q URI
978 if err := q.decode(nil, vs[0].Data); err != nil {
979 return fmt.Errorf(errDecodingType, cURI, err)
980 }
981 *t = ParamURI(q)
982 return nil
983 }
984
985 func (t ParamURI) encode(w writer) {
986 if len(t.String()) == 0 {
987 return
988 }
989 w.WriteString(";URI=")
990 q := URI(t)
991 q.encode(w)
992 }
993
994 func (t ParamURI) valid() error {
995 q := URI(t)
996 if err := q.valid(); err != nil {
997 return fmt.Errorf(errValidatingType, cURI, err)
998 }
999 return nil
1000 }
1001
1002 // ID
1003 type ParamID string
1004
1005 // NewID returns a *ParamID for ease of use with optional values
1006 func NewID(v ParamID) *ParamID {
1007 return &v
1008 }
1009
1010 func (t *ParamID) decode(vs []parser.Token) error {
1011 if len(vs) != 1 {
1012 return fmt.Errorf(errDecodingType, cID, ErrInvalidParam)
1013 }
1014 if vs[0].Type != tokenParamQuotedValue {
1015 return fmt.Errorf(errDecodingType, cID, ErrInvalidParam)
1016 }
1017 *t = ParamID(decode6868(vs[0].Data))
1018 return nil
1019 }
1020
1021 func (t ParamID) encode(w writer) {
1022 if len(t) == 0 {
1023 return
1024 }
1025 w.WriteString(";ID=")
1026 w.WriteString("\"")
1027 w.Write(encode6868(string(t)))
1028 w.WriteString("\"")
1029 }
1030
1031 func (t ParamID) valid() error {
1032 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
1033 return fmt.Errorf(errValidatingType, cID, ErrInvalidText)
1034 }
1035 return nil
1036 }
1037
1038 // AgentID
1039 type ParamAgentID string
1040
1041 // NewAgentID returns a *ParamAgentID for ease of use with optional values
1042 func NewAgentID(v ParamAgentID) *ParamAgentID {
1043 return &v
1044 }
1045
1046 func (t *ParamAgentID) decode(vs []parser.Token) error {
1047 if len(vs) != 1 {
1048 return fmt.Errorf(errDecodingType, cAgentID, ErrInvalidParam)
1049 }
1050 if vs[0].Type != tokenParamQuotedValue {
1051 return fmt.Errorf(errDecodingType, cAgentID, ErrInvalidParam)
1052 }
1053 *t = ParamAgentID(decode6868(vs[0].Data))
1054 return nil
1055 }
1056
1057 func (t ParamAgentID) encode(w writer) {
1058 if len(t) == 0 {
1059 return
1060 }
1061 w.WriteString(";AGENT-ID=")
1062 w.WriteString("\"")
1063 w.Write(encode6868(string(t)))
1064 w.WriteString("\"")
1065 }
1066
1067 func (t ParamAgentID) valid() error {
1068 if strings.ContainsAny(string(t), nonsafeChars[:31]) {
1069 return fmt.Errorf(errValidatingType, cAgentID, ErrInvalidText)
1070 }
1071 return nil
1072 }
1073
1074 func decode6868(s string) string {
1075 t := parser.NewStringTokeniser(s)
1076 d := make([]byte, 0, len(s))
1077 var ru [4]byte
1078 Loop:
1079 for {
1080 c := t.ExceptRun("^")
1081 d = append(d, t.Get()...)
1082 switch c {
1083 case -1:
1084 break Loop
1085 case '^':
1086 t.Accept("^")
1087 switch t.Peek() {
1088 case -1:
1089 d = append(d, '^')
1090 break Loop
1091 case 'n':
1092 d = append(d, '\n')
1093 case '\'':
1094 d = append(d, '"')
1095 case '^':
1096 d = append(d, '^')
1097 default:
1098 d = append(d, '^')
1099 l := utf8.EncodeRune(ru[:], c)
1100 d = append(d, ru[:l]...)
1101 }
1102 t.Except("")
1103 }
1104 }
1105 return string(d)
1106 }
1107
1108 func encode6868(s string) []byte {
1109 t := parser.NewStringTokeniser(s)
1110 d := make([]byte, 0, len(s))
1111 Loop:
1112 for {
1113 c := t.ExceptRun("\n^\"")
1114 d = append(d, t.Get()...)
1115 switch c {
1116 case -1:
1117 break Loop
1118 case '\n':
1119 d = append(d, '^', 'n')
1120 case '^':
1121 d = append(d, '^', '^')
1122 case '"':
1123 d = append(d, '^', '\'')
1124 }
1125 }
1126 return d
1127 }
1128
1129 func init() {
1130 regexFormatType = regexp.MustCompile("[A-Za-z0-9!#$&.+-^_]/[A-Za-z0-9!#$&.+-^_]")
1131 }
1132
1133 // Errors
1134 var (
1135 ErrInvalidParam = errors.New("invalid param value")
1136 ErrInvalidValue = errors.New("invalid value")
1137 )
1138
1139 const (
1140 errDecodingType = "error decoding %s: %w"
1141 errValidatingType = "error decoding %s: %w"
1142 cAlternativeRepresentation = "AlternativeRepresentation"
1143 cCommonName = "CommonName"
1144 cCalendarUserType = "CalendarUserType"
1145 cDelegator = "Delegator"
1146 cDelagatee = "Delagatee"
1147 cDirectoryEntry = "DirectoryEntry"
1148 cEncoding = "Encoding"
1149 cFormatType = "FormatType"
1150 cFreeBusyType = "FreeBusyType"
1151 cLanguage = "Language"
1152 cMember = "Member"
1153 cParticipationStatus = "ParticipationStatus"
1154 cRange = "Range"
1155 cRelated = "Related"
1156 cRelationshipType = "RelationshipType"
1157 cParticipationRole = "ParticipationRole"
1158 cRSVP = "RSVP"
1159 cSentBy = "SentBy"
1160 cTimezoneID = "TimezoneID"
1161 cValue = "Value"
1162 cURI = "URI"
1163 cID = "ID"
1164 cAgentID = "AgentID"
1165 )