1// SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
2//
3// SPDX-License-Identifier: AGPL-3.0-or-later
4
5package lunatask
6
7import (
8 "encoding/json"
9 "errors"
10 "fmt"
11 "strings"
12)
13
14// Errors returned by Priority operations.
15var (
16 // ErrInvalidPriority is returned when parsing an unknown priority string.
17 ErrInvalidPriority = errors.New("invalid priority")
18 // ErrPriorityOutOfRange is returned when a priority value is outside [-2, 2].
19 ErrPriorityOutOfRange = errors.New("priority out of range")
20)
21
22// Priority represents task priority level from lowest (-2) to highest (2).
23// The default priority is [PriorityNormal] (0).
24type Priority int
25
26// Task priority levels. See [Priority] for the full range.
27const (
28 PriorityLowest Priority = -2
29 PriorityLow Priority = -1
30 PriorityNormal Priority = 0
31 PriorityHigh Priority = 1
32 PriorityHighest Priority = 2
33)
34
35// String returns the lowercase name of the priority level.
36func (p *Priority) String() string {
37 switch *p {
38 case PriorityLowest:
39 return "lowest"
40 case PriorityLow:
41 return "low"
42 case PriorityNormal:
43 return "normal"
44 case PriorityHigh:
45 return "high"
46 case PriorityHighest:
47 return "highest"
48 default:
49 return fmt.Sprintf("Priority(%d)", *p)
50 }
51}
52
53// Valid reports whether the priority is within the valid range [-2, 2].
54func (p *Priority) Valid() bool {
55 return *p >= PriorityLowest && *p <= PriorityHighest
56}
57
58// ParsePriority parses a string to a Priority value (case-insensitive).
59// Valid values: "lowest", "low", "normal", "high", "highest".
60func ParsePriority(str string) (Priority, error) {
61 switch strings.ToLower(str) {
62 case "lowest":
63 return PriorityLowest, nil
64 case "low":
65 return PriorityLow, nil
66 case "normal":
67 return PriorityNormal, nil
68 case "high":
69 return PriorityHigh, nil
70 case "highest":
71 return PriorityHighest, nil
72 default:
73 return 0, fmt.Errorf("%w: %q", ErrInvalidPriority, str)
74 }
75}
76
77// MarshalJSON implements [json.Marshaler].
78// Priority marshals as its integer value.
79func (p *Priority) MarshalJSON() ([]byte, error) {
80 data, err := json.Marshal(int(*p))
81 if err != nil {
82 return nil, fmt.Errorf("marshaling priority: %w", err)
83 }
84
85 return data, nil
86}
87
88// UnmarshalJSON implements [json.Unmarshaler].
89// Priority unmarshals from an integer value in the range [-2, 2].
90func (p *Priority) UnmarshalJSON(data []byte) error {
91 if string(data) == "null" {
92 *p = PriorityNormal
93
94 return nil
95 }
96
97 var val int
98 if err := json.Unmarshal(data, &val); err != nil {
99 return fmt.Errorf("priority must be an integer: %w", err)
100 }
101
102 if val < -2 || val > 2 {
103 return fmt.Errorf("%w: %d", ErrPriorityOutOfRange, val)
104 }
105
106 *p = Priority(val)
107
108 return nil
109}