/
enums.ts
81 lines (69 loc) · 2.3 KB
/
enums.ts
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
import { CoerceError } from "../shared-classes"
import { isNumber } from "../utils/isNumber"
import { keys } from "../utils/objects"
export function enumStringToInt(value: number | string | null | undefined, type: EnumTypeMetadata): number | null {
// if it's number already, just return it
if (value == null) {
return null
}
if (isNumber(value)) {
return +value
}
if (value in type.values) {
return type.values[value]
}
if (type.isFlags) {
// flags - comma-separated values
const parts = (value as string).split(',')
let result = 0
for (const fragment of parts) {
// trim the value if needed
const trimmed = fragment.trim()
if (trimmed in type.values) {
result |= type.values[trimmed]
}
else {
return null
}
}
return result
}
return null
}
export function enumIntToString(value: number, type: EnumTypeMetadata): string | null {
value |= 0
const matched = keys(type.values).filter(k => type.values[k] === value)
if (matched.length) {
return matched[0]
}
if (type.isFlags) {
// try to represent the enum with comma-separated strings
if (value) {
let result: number = value
let stringValue = ""
for (const k of keys(type.values).reverse()) {
if (type.values[k] !== 0 && (result & type.values[k]) === type.values[k]) {
result -= type.values[k]
if (stringValue !== "") stringValue = "," + stringValue
stringValue = k + stringValue
}
}
if (!result) {
return stringValue
}
}
}
return null
}
export function tryCoerceEnum(value: any, type: EnumTypeMetadata): CoerceResult {
if (value in type.values) {
return { value }
}
const intValue = enumStringToInt(value, type)
if (intValue != null) {
const coercedValue = enumIntToString(intValue, type) ?? intValue
const wasCoerced = coercedValue != value
return { value: coercedValue, wasCoerced }
}
return new CoerceError(`Cannot cast '${value}' to type 'Enum(${keys(type.values).join(",")})'.`)
}