Skip to content

Commit

Permalink
f
Browse files Browse the repository at this point in the history
  • Loading branch information
lost committed Mar 30, 2024
1 parent abde28f commit 6194154
Showing 1 changed file with 20 additions and 1 deletion.
21 changes: 20 additions & 1 deletion src/dig.gleam
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,14 @@ import gleam/int
import gleam/iterator

/// wrap `dynamic.Decoder` with a path
///
pub type DigDecoder {
DigObject(path: List(String), inner: Decoder(Dynamic))
DigList(path: List(String), inner: Decoder(List(Dynamic)))
}

/// get path of `DigDecoder`
///
pub fn get_path(dig_decoder: DigDecoder) -> List(String) {
case dig_decoder {
DigObject(path, _) -> path
Expand All @@ -26,13 +28,16 @@ pub type DigError {
}

/// `Ok(DigDecoder)` or `Error(DigError)`
///
pub type DigResult =
Result(DigDecoder, DigError)

/// dig `dynamic.Encoder` in path
///
pub fn dig(path: List(String)) -> DigResult {
case path {
[] -> Error(EmptyPath)

[first, ..rest] -> {
use first_dig_decoder <- try(dig_path_seg_with_path([], first))
rest
Expand All @@ -50,6 +55,7 @@ pub fn dig(path: List(String)) -> DigResult {
}

/// dig `dynamic.Decoder` in single path segment
///
pub fn dig_path_seg(path_seg: String) -> DigResult {
dig_path_seg_with_path([], path_seg)
}
Expand Down Expand Up @@ -113,10 +119,15 @@ fn dig_path_seg_with_path(
case parsed_path_seg {
// Object
Object(key) -> DigObject(path, dynamic.field(key, dynamic.dynamic))

// List
List(Some(key), None) ->
DigList(path, dynamic.field(key, dynamic.list(dynamic.dynamic)))

// List
List(None, None) -> DigList(path, dynamic.list(dynamic.dynamic))

// List
List(Some(key), Some(index)) ->
DigObject(
path,
Expand All @@ -136,6 +147,8 @@ fn dig_path_seg_with_path(
])
}),
)

// List
List(None, Some(index)) ->
DigObject(path, fn(d) {
use shallow_list <- try(
Expand All @@ -156,6 +169,8 @@ fn dig_path_seg_with_path(
|> Ok()
}

// ------ PathSeg -------------------------

pub type PathSeg {
Object(key: String)
List(key: Option(String), index: Option(Int))
Expand All @@ -169,13 +184,15 @@ pub type PathSegParseResult =
Result(PathSeg, PathSegParseError)

/// parse single path segment
///
pub fn parse_path_seg(path_seg: String) -> PathSegParseResult {
parse_object_path_seg(path_seg)
|> result.lazy_or(fn() { parse_list_path_seg(path_seg) })
}

fn parse_object_path_seg(path_seg: String) -> PathSegParseResult {
let assert Ok(obj_regex) = regex.from_string("^\\w+$")

case regex.scan(with: obj_regex, content: path_seg) {
[] -> Error(InvalidPathSeg(path_seg))
[first, ..] -> Ok(Object(first.content))
Expand All @@ -186,6 +203,7 @@ fn parse_list_path_seg(path_seg: String) -> PathSegParseResult {
let assert Ok(list_regex) = regex.from_string("^(\\w*)\\[(\\d*)\\]$")
case regex.scan(with: list_regex, content: path_seg) {
[] -> Error(InvalidPathSeg(path_seg))

[first, ..] -> {
use key <- try(
first.submatches
Expand All @@ -197,15 +215,16 @@ fn parse_list_path_seg(path_seg: String) -> PathSegParseResult {
|> list.at(1)
|> replace_error(InvalidPathSeg(path_seg)),
)

case index_option {
None -> Ok(List(key, None))
Some(v) -> {
use index <- try(
int.parse(v)
|> replace_error(InvalidPathSeg(path_seg)),
)
Ok(List(key, Some(index)))
}
None -> Ok(List(key, None))
}
}
}
Expand Down

0 comments on commit 6194154

Please sign in to comment.