
Selection.pudu
Pudu72 lines2.5 KB
1/** @Validation.Selection.Paths — relates requested and concrete property paths */2module PuduLangValidator.Selection34import Std.Text as Text567export fn covers(requested: Str, path: Str) -> Bool {8 match scan(requested, path) {9 case Some((requestEnd, pathEnd)) => {10 let chars = path.chars()11 requestEnd == requested.length() && boundary(&chars, pathEnd)12 }13 case None => false14 }15}161718export fn overlaps(requested: Str, path: Str) -> Bool {19 match scan(requested, path) {20 case Some((requestEnd, pathEnd)) => {21 let requestedChars = requested.chars()22 let pathChars = path.chars()23 (requestEnd == requestedChars.length() && boundary(&pathChars, pathEnd)) ||24 (pathEnd == pathChars.length() && boundary(&requestedChars, requestEnd))25 }26 case None => false27 }28}293031export fn relative(requested: Str, prefix: Str) -> Option[Str] {32 let positions = scan(requested, prefix) ?33 let requestEnd = positions[0]34 let prefixEnd = positions[1]35 if prefixEnd != prefix.length() { return None }36 let chars = requested.chars()37 if requestEnd == chars.length() { return Some("") }38 if chars[requestEnd] == '.' { Some(Text.drop(requested, requestEnd + 1)) } else { None }39}404142fn boundary(chars: &Array[Char], index: Int) -> Bool {43 index == chars.length() || chars[index] == '.' || chars[index] == '['44}454647fn scan(requested: Str, path: Str) -> Option[(Int, Int)] {48 let requestChars = requested.chars()49 let pathChars = path.chars()50 var requestAt = 051 var pathAt = 052 while requestAt < requestChars.length() && pathAt < pathChars.length() {53 if requestChars[requestAt] == '[' && requestAt + 1 < requestChars.length() && requestChars[requestAt + 1] == ']' {54 if pathChars[pathAt] != '[' { return None }55 pathAt = pathAt + 156 let first = pathAt57 while pathAt < pathChars.length() && pathChars[pathAt] != ']' {58 if pathChars[pathAt] == '[' { return None }59 pathAt = pathAt + 160 }61 if pathAt == first || pathAt == pathChars.length() { return None }62 requestAt = requestAt + 263 pathAt = pathAt + 164 } else {65 if requestChars[requestAt] != pathChars[pathAt] { return None }66 requestAt = requestAt + 167 pathAt = pathAt + 168 }69 }70 Some((requestAt, pathAt))71}72