|
7 | 7 | "sort" |
8 | 8 | "strconv" |
9 | 9 | "strings" |
| 10 | + "unicode" |
| 11 | + "unicode/utf8" |
10 | 12 |
|
11 | 13 | "github.com/specterops/dawgs/cypher/models/cypher" |
12 | 14 | "github.com/specterops/dawgs/cypher/models/walk" |
@@ -264,25 +266,29 @@ func sortedPropertyKeys(properties map[string]any) []string { |
264 | 266 | return keys |
265 | 267 | } |
266 | 268 |
|
267 | | -func isCypherSymbolStart(char byte) bool { |
268 | | - return char == '_' || (char >= 'A' && char <= 'Z') || (char >= 'a' && char <= 'z') |
| 269 | +func isCypherSymbolStart(char rune) bool { |
| 270 | + return char == '_' || unicode.IsLetter(char) || unicode.In(char, unicode.Nl, unicode.Pc) |
269 | 271 | } |
270 | 272 |
|
271 | | -func isCypherSymbolPart(char byte) bool { |
272 | | - return isCypherSymbolStart(char) || (char >= '0' && char <= '9') |
| 273 | +func isCypherSymbolPart(char rune) bool { |
| 274 | + return isCypherSymbolStart(char) || unicode.IsDigit(char) || unicode.In(char, unicode.Mark, unicode.Sc) |
273 | 275 | } |
274 | 276 |
|
275 | 277 | func validateCypherSymbol(symbol, context string) error { |
276 | 278 | if strings.TrimSpace(symbol) == "" { |
277 | 279 | return fmt.Errorf("%s is empty", context) |
278 | 280 | } |
279 | 281 |
|
280 | | - if !isCypherSymbolStart(symbol[0]) { |
| 282 | + if !utf8.ValidString(symbol) { |
281 | 283 | return fmt.Errorf("%s has invalid symbol %q", context, symbol) |
282 | 284 | } |
283 | 285 |
|
284 | | - for idx := 1; idx < len(symbol); idx++ { |
285 | | - if !isCypherSymbolPart(symbol[idx]) { |
| 286 | + for idx, char := range symbol { |
| 287 | + if idx == 0 { |
| 288 | + if !isCypherSymbolStart(char) { |
| 289 | + return fmt.Errorf("%s has invalid symbol %q", context, symbol) |
| 290 | + } |
| 291 | + } else if !isCypherSymbolPart(char) { |
286 | 292 | return fmt.Errorf("%s has invalid symbol %q", context, symbol) |
287 | 293 | } |
288 | 294 | } |
|
0 commit comments