Skip to content

Commit 38bbad4

Browse files
committed
feat: Error harder if values and types are inconsistent
1 parent f4dc840 commit 38bbad4

File tree

8 files changed

+170
-120
lines changed

8 files changed

+170
-120
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,4 @@ bpm install
5959
- add tests for array in array (like object in object)
6060
- ensure error (for set primarily) if the virtual object references a variable that does not exist
6161
- "queried for X, but found existing object": print object in error (same with indexed arrays)
62+
- zerocopy for get and set

pkg/lib/cmd/bobject.sh

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -10,55 +10,25 @@ bobject() {
1010

1111
case "$subcmd" in
1212
get-string)
13-
if (($# != 2)); then
14-
printf '%s\n' "bash-object: Error: Incorrect arguments for subcommand '$subcmd'"
15-
return 1
16-
fi
17-
1813
bash_object.traverse-get string "$@"
1914
;;
2015
get-array)
21-
if (($# != 2)); then
22-
printf '%s\n' "bash-object: Error: Incorrect arguments for subcommand '$subcmd'"
23-
return 1
24-
fi
25-
2616
bash_object.traverse-get array "$@"
2717
;;
2818
get-object)
29-
if (($# != 2)); then
30-
printf '%s\n' "bash-object: Error: Incorrect arguments for subcommand '$subcmd'"
31-
return 1
32-
fi
33-
3419
bash_object.traverse-get object "$@"
3520
;;
3621
set-string)
37-
if (($# != 3)); then
38-
printf '%s\n' "bash-object: Error: Incorrect arguments for subcommand '$subcmd'"
39-
return 1
40-
fi
41-
4222
bash_object.traverse-set string "$@"
4323
;;
4424
set-array)
45-
if (($# != 3)); then
46-
printf '%s\n' "bash-object: Error: Incorrect arguments for subcommand '$subcmd'"
47-
return 1
48-
fi
49-
5025
bash_object.traverse-set array "$@"
5126
;;
5227
set-object)
53-
if (($# != 3)); then
54-
printf '%s\n' "bash-object: Error: Incorrect arguments for subcommand '$subcmd'"
55-
return 1
56-
fi
57-
5828
bash_object.traverse-set object "$@"
5929
;;
6030
*)
61-
printf '%s\n' "bash-object: Error: Subcommand '$subcmd' not recognized"
62-
return 1
31+
bash_object.util.die 'ERROR_INVALID_ARGS' "Subcommand '$subcmd' not recognized"
32+
return
6333
esac
6434
}

pkg/lib/parse.sh

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,14 @@ bash_object.parse_filter() {
99

1010
local flag_parser_type=
1111

12-
for arg; do
13-
case "$arg" in
14-
-s|--simple)
15-
flag_parser_type='simple'
16-
shift
17-
;;
18-
-a|--advanced)
19-
flag_parser_type='advanced'
20-
shift
21-
;;
22-
esac
23-
done
12+
for arg; do case "$arg" in
13+
-s|--simple)
14+
flag_parser_type='simple'
15+
shift ;;
16+
-a|--advanced)
17+
flag_parser_type='advanced'
18+
shift ;;
19+
esac done
2420

2521
local filter="$1"
2622

pkg/lib/traverse-get.sh

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@ bash_object.traverse-get() {
1212
local root_object_name="$2"
1313
local filter="$3"
1414

15+
if (( $# != 3)); then
16+
bash_object.util.die 'ERROR_INVALID_ARGS' "Incorrect arguments for subcommand 'get-$final_value_type'"
17+
return
18+
fi
19+
1520
# Start traversing at the root object
1621
local current_object_name="$root_object_name"
1722
local -n current_object="$root_object_name"
@@ -81,7 +86,7 @@ bash_object.traverse-get() {
8186
# fi
8287
# ;;
8388
# *)
84-
# bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "vmd_dtype: $vmd_dtype"
89+
# bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "Unexpected vmd_dtype '$vmd_dtype'"
8590
# return
8691
# ;;
8792
# esac
@@ -101,7 +106,7 @@ bash_object.traverse-get() {
101106
return
102107
;;
103108
*)
104-
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "vmd_dtype: $vmd_dtype"
109+
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "Unexpected vmd_dtype '$vmd_dtype'"
105110
return
106111
;;
107112
esac
@@ -117,7 +122,7 @@ bash_object.traverse-get() {
117122
REPLY=("${current_object[@]}")
118123
;;
119124
*)
120-
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "vmd_dtype: $vmd_dtype"
125+
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "Unexpected vmd_dtype '$vmd_dtype'"
121126
return
122127
;;
123128
esac
@@ -132,11 +137,11 @@ bash_object.traverse-get() {
132137
return
133138
;;
134139
*)
135-
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "vmd_dtype: $vmd_dtype"
140+
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "Unexpected vmd_dtype '$vmd_dtype'"
136141
return
137142
esac
138143
else
139-
bash_object.util.die 'ERROR_INTERNAL_INVALID_PARAM' "final_value_type: $final_value_type"
144+
bash_object.util.die 'ERROR_INTERNAL_INVALID_PARAM' "Unexpected final_value_type '$final_value_type'"
140145
return
141146
fi
142147
fi

pkg/lib/traverse-set.sh

Lines changed: 68 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,70 @@ bash_object.traverse-set() {
1111
local filter="$3"
1212
local final_value="$4"
1313

14-
# TODO: test, old versions of bash
15-
if [[ ! -v 4 ]]; then
16-
bash_object.util.die 'ERROR_INTERNAL_MISCELLANEOUS' "final_value is empty"
14+
if (( $# != 4)); then
15+
bash_object.util.die 'ERROR_INVALID_ARGS' "Incorrect arguments for subcommand 'set-$final_value_type'"
16+
return
17+
fi
18+
19+
# TODO test
20+
# Ensure parameters are not empty
21+
local variable=
22+
for variable_name in final_value_type root_object_name filter; do
23+
local -n variable="$variable_name"
24+
25+
if [ -z "$variable" ]; then
26+
bash_object.util.die 'ERROR_INVALID_ARGS' "Variable '$variable' is empty. Please check passed parameters"
27+
return
28+
fi
29+
done
30+
31+
if [ -n "${VERIFY_BASH_OBJECT+x}" ]; then
32+
# TODO: test
33+
# Check 'root_object_name'
34+
local root_object_type=
35+
if root_object_type="$(declare -p "$root_object_name" 2>/dev/null)"; then :; else
36+
bash_object.util.die 'ERROR_INVALID_ARGS' "The final value of '$root_object_name' does not exist"
37+
return
38+
fi
39+
root_object_type="${root_object_type#declare -}"
40+
if [ "${root_object_type::1}" != 'A' ]; then
41+
bash_object.util.die 'ERROR_VALUE_INCORRECT_TYPE' "The root object must have a type of 'object'"
1742
return
43+
fi
44+
45+
# TODO: test
46+
# Check 'final_value' for type correctness
47+
if [ "$final_value_type" != string ]; then
48+
local actual_final_value_type=
49+
if ! actual_final_value_type="$(declare -p "$final_value" 2>/dev/null)"; then
50+
bash_object.util.die 'ERROR_INVALID_ARGS' "The final value of '$final_value' does not exist"
51+
return
52+
fi
53+
actual_final_value_type="${actual_final_value_type#declare -}"
54+
case "${actual_final_value_type::1}" in
55+
A) actual_final_value_type='object' ;;
56+
a) actual_final_value_type='array' ;;
57+
i) actual_final_value_type='integer' ;;
58+
-) actual_final_value_type='string' ;;
59+
*) actual_final_value_type='unknown' ;;
60+
esac
61+
62+
if [ "$final_value_type" == object ]; then
63+
if [ "$actual_final_value_type" != object ]; then
64+
bash_object.util.die 'ERROR_VALUE_INCORRECT_TYPE' "The type of the final value was expected to be '$final_value_type', but was actually '$actual_final_value_type'"
65+
return
66+
fi
67+
elif [ "$final_value_type" == array ]; then
68+
if [ "$actual_final_value_type" != array ]; then
69+
bash_object.util.die 'ERROR_VALUE_INCORRECT_TYPE' "The type of the final value was expected to be '$final_value_type', but was actually '$actual_final_value_type'"
70+
return
71+
fi
72+
else
73+
# case 'string' is handled above
74+
bash_object.util.die 'ERROR_INTERNAL_INVALID_PARAM' "Unexpected final_value_type '$final_value_type $actual_final_value_type'"
75+
return
76+
fi
77+
fi
1878
fi
1979

2080
# Start traversing at the root object
@@ -117,7 +177,7 @@ bash_object.traverse-set() {
117177
elif [ "$final_value_type" = string ]; then
118178
current_object["$key"]="$final_value"
119179
else
120-
bash_object.util.die 'ERROR_INTERNAL_INVALID_PARAM' "final_value_type: $final_value_type"
180+
bash_object.util.die 'ERROR_INTERNAL_INVALID_PARAM' "Unexpected final_value_type '$final_value_type'"
121181
return
122182
fi
123183
fi
@@ -151,7 +211,7 @@ bash_object.traverse-set() {
151211
return
152212
;;
153213
*)
154-
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "vmd_dtype: $vmd_dtype"
214+
bash_object.util.die 'ERROR_INTERNAL_INVALID_VOBJ' "Unexpected vmd_dtype '$vmd_dtype'"
155215
return
156216
;;
157217
esac
@@ -163,37 +223,11 @@ bash_object.traverse-set() {
163223
fi
164224

165225
if ((i+1 < ${#REPLIES[@]})); then
166-
echo "omicron" >&3
226+
# TODO error message
227+
bash_object.util.die 'ERROR_VALUE_NOT_FOUND' "Encountered string using accessor '$key', but expected to find either an object or array, in accordance with the filter"
228+
return
167229
:
168230
elif ((i+1 == ${#REPLIES[@]})); then
169-
if [ "$final_value_type" = object ]; then
170-
case "$vmd_dtype" in
171-
object)
172-
173-
;;
174-
array)
175-
;;
176-
esac
177-
elif [ "$final_value_type" = array ]; then
178-
case "$vmd_dtype" in
179-
object)
180-
;;
181-
array)
182-
;;
183-
esac
184-
elif [ "$final_value_type" = string ]; then
185-
case "$vmd_dtype" in
186-
object)
187-
# TODO: test this
188-
echo "Error: Cannot set string on object"
189-
return 1
190-
;;
191-
array)
192-
echo "Error: Cannot set string on array"
193-
return 1
194-
;;
195-
esac
196-
fi
197231
current_object["$key"]="$final_value"
198232
fi
199233
fi

pkg/lib/util/util.sh

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,39 @@
11
# shellcheck shell=bash
22

3+
# shellcheck disable=SC2192
34
declare -gA ERRORS_BASH_OBJECT=(
4-
[ERROR_VALUE_NOT_FOUND]='Attempted to access either a member of an object or an index of an array, but the member or index does not exist'
5-
[ERROR_VALUE_INCORRECT_TYPE]='Attempted to get or set a value, but somewhere a value with a different type was expected'
6-
[ERROR_INVALID_FILTER]='The supplied filter is invalid'
7-
[ERROR_INVALID_ARGS]='Invalid arguments'
8-
[ERROR_INTERNAL_INVALID_VOBJ]='Internal virtual object has incorrect metadata'
9-
[ERROR_INTERNAL_INVALID_PARAM]='Internal parameter has an incorrect value'
10-
[ERROR_INTERNAL_MISCELLANEOUS]='Miscellaneous error occured'
5+
[ERROR_VALUE_NOT_FOUND]=
6+
[ERROR_VALUE_INCORRECT_TYPE]=
7+
[ERROR_INVALID_FILTER]=
8+
[ERROR_INVALID_ARGS]=
9+
[ERROR_INTERNAL_INVALID_VOBJ]=
10+
[ERROR_INTERNAL_INVALID_PARAM]=
11+
[ERROR_INTERNAL_MISCELLANEOUS]=
1112
)
1213

1314
bash_object.util.die() {
1415
local error_key="$1"
1516
local error_context="${2:-<empty>}"
1617

17-
local error_message="${ERRORS_BASH_OBJECT["$error_key"]}"
18+
# TODO: test
19+
# if [[ ! -v 'ERRORS_BASH_OBJECT["$error_key"]' ]]; then
20+
# return 77
21+
# fi
1822

1923
local error_output=
2024
case "$error_key" in
2125
ERROR_INVALID_FILTER)
2226
printf -v error_output 'Failed to parse filter:
2327
-> code: %s
24-
-> message: %s
2528
-> context: %s
2629
-> PARSER_COLUMN_NUMBER: %s
27-
' "$error_key" "$error_message" "$error_context" "$PARSER_COLUMN_NUMBER"
30+
' "$error_key" "$error_context" "$PARSER_COLUMN_NUMBER"
2831
;;
2932
*)
3033
printf -v error_output 'Failed to perform operation:
3134
-> code: %s
32-
-> message: %s
3335
-> context: %s
34-
' "$error_key" "$error_message" "$error_context"
36+
' "$error_key" "$error_context"
3537
;;
3638
esac
3739

0 commit comments

Comments
 (0)