aboutsummaryrefslogtreecommitdiffhomepage
path: root/crates/shirabe/src/json
diff options
context:
space:
mode:
authornsfisis <nsfisis@gmail.com>2026-08-02 17:32:43 +0900
committernsfisis <nsfisis@gmail.com>2026-08-02 17:32:43 +0900
commit7e31bab9ff7209c9b6d7928a581d7a449846f42e (patch)
treeb121966a169ee74afe04d066576e862a6702bbf6 /crates/shirabe/src/json
parentebcb4a7f013c0511dd6617686395cef17822d1e2 (diff)
downloadphp-shirabe-7e31bab9ff7209c9b6d7928a581d7a449846f42e.tar.gz
php-shirabe-7e31bab9ff7209c9b6d7928a581d7a449846f42e.tar.zst
php-shirabe-7e31bab9ff7209c9b6d7928a581d7a449846f42e.zip
fix(json): propagate JsonFile::encode errors instead of unwrapping
PHP's JsonFile::encode throws a RuntimeException when json_encode fails; the port swallowed that into an .unwrap() marked TODO(phase-c). Return anyhow::Result from encode/encode_with_options and propagate at every call site (print_table and list_repositories become Result-returning to carry it). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Diffstat (limited to 'crates/shirabe/src/json')
-rw-r--r--crates/shirabe/src/json/json_file.rs24
-rw-r--r--crates/shirabe/src/json/json_manipulator.rs74
2 files changed, 51 insertions, 47 deletions
diff --git a/crates/shirabe/src/json/json_file.rs b/crates/shirabe/src/json/json_file.rs
index cba11f01..632519a7 100644
--- a/crates/shirabe/src/json/json_file.rs
+++ b/crates/shirabe/src/json/json_file.rs
@@ -220,7 +220,7 @@ impl JsonFile {
if self.path == "php://memory" {
file_put_contents(
&self.path,
- Self::encode_with_options(&hash, options).as_bytes(),
+ Self::encode_with_options(&hash, options)?.as_bytes(),
);
return Ok(());
@@ -256,7 +256,7 @@ impl JsonFile {
&self.path,
&format!(
"{}{}",
- Self::encode_with_options(&hash, options.clone()),
+ Self::encode_with_options(&hash, options.clone())?,
if options.pretty_print { "\n" } else { "" },
),
)?;
@@ -443,25 +443,23 @@ impl JsonFile {
Ok(true)
}
- pub fn encode<T: serde::Serialize + ?Sized>(data: &T) -> String {
+ pub fn encode<T: serde::Serialize + ?Sized>(data: &T) -> anyhow::Result<String> {
Self::encode_with_options(data, JsonEncodeOptions::default())
}
pub fn encode_with_options<T: serde::Serialize + ?Sized>(
data: &T,
options: JsonEncodeOptions,
- ) -> String {
- let json = json_encode_ex(data, options.to_flags())
- .map_err(|err| RuntimeException {
- message: format!("JSON encoding failed: {}", err),
- code: 0,
- })
- .unwrap(); // TODO(phase-c): propagating an Err.
+ ) -> anyhow::Result<String> {
+ let json = json_encode_ex(data, options.to_flags()).map_err(|err| RuntimeException {
+ message: format!("JSON encoding failed: {}", err),
+ code: 0,
+ })?;
if options.pretty_print && options.indent != Self::INDENT_DEFAULT {
// Pretty printing and not using default indentation
let indent_owned = options.indent;
- return Preg::replace_callback(
+ return Ok(Preg::replace_callback(
php_regex!(r"#^ {4,}#m"),
move |m: &indexmap::IndexMap<
shirabe_external_packages::composer::pcre::CaptureKey,
@@ -475,10 +473,10 @@ impl JsonFile {
str_repeat(&indent_owned, (strlen(whole) / 4) as usize)
},
&json,
- );
+ ));
}
- json
+ Ok(json)
}
/// Parses json string and returns hash.
diff --git a/crates/shirabe/src/json/json_manipulator.rs b/crates/shirabe/src/json/json_manipulator.rs
index 3647e846..48500de2 100644
--- a/crates/shirabe/src/json/json_manipulator.rs
+++ b/crates/shirabe/src/json/json_manipulator.rs
@@ -85,7 +85,7 @@ impl JsonManipulator {
let m = match json_grammar::find_top_level_key(
self.contents.as_bytes(),
- JsonFile::encode(r#type).as_bytes(),
+ JsonFile::encode(r#type)?.as_bytes(),
ValueKind::Json,
) {
Some(m) => m,
@@ -107,7 +107,7 @@ impl JsonManipulator {
links = format!(
"{}{}{}\"{}\"{}",
&links[..key_start],
- JsonFile::encode(&str_replace("\\/", "/", &existing_package)),
+ JsonFile::encode(&str_replace("\\/", "/", &existing_package))?,
separator,
constraint,
&links[value_end..]
@@ -133,8 +133,8 @@ impl JsonManipulator {
self.newline,
self.indent,
self.indent,
- JsonFile::encode(package),
- JsonFile::encode(constraint),
+ JsonFile::encode(package)?,
+ JsonFile::encode(constraint)?,
groups_1
),
"\\$",
@@ -148,8 +148,8 @@ impl JsonManipulator {
self.newline,
self.indent,
self.indent,
- JsonFile::encode(package),
- JsonFile::encode(constraint),
+ JsonFile::encode(package)?,
+ JsonFile::encode(constraint)?,
self.newline,
self.indent
);
@@ -375,22 +375,28 @@ impl JsonManipulator {
Some((i, e))
})
} else {
- json_grammar::find_top_level_key(
- self.contents.as_bytes(),
- b"\"repositories\"",
- ValueKind::Object,
- )
- .and_then(|reps| {
- let obj = self.contents[reps.value_pos..reps.value_end].to_string();
- let key = JsonFile::encode(&repository_index);
- json_grammar::find_top_level_key(obj.as_bytes(), key.as_bytes(), ValueKind::Object)
+ {
+ let key = JsonFile::encode(&repository_index)?;
+ json_grammar::find_top_level_key(
+ self.contents.as_bytes(),
+ b"\"repositories\"",
+ ValueKind::Object,
+ )
+ .and_then(|reps| {
+ let obj = self.contents[reps.value_pos..reps.value_end].to_string();
+ json_grammar::find_top_level_key(
+ obj.as_bytes(),
+ key.as_bytes(),
+ ValueKind::Object,
+ )
.map(|inner| {
(
reps.value_pos + inner.value_pos,
reps.value_pos + inner.value_end,
)
})
- })
+ })
+ }
};
let (repo_pos, repo_end) = match repo_span {
@@ -416,7 +422,7 @@ impl JsonManipulator {
Some(u) => format!(
"{}{}{}",
&raw_repo[..u.value_pos],
- JsonFile::encode(url),
+ JsonFile::encode(url)?,
&raw_repo[u.value_end..]
),
None => raw_repo,
@@ -692,7 +698,7 @@ impl JsonManipulator {
// main node content not match-able
let node = match json_grammar::find_top_level_key(
self.contents.as_bytes(),
- JsonFile::encode(main_node).as_bytes(),
+ JsonFile::encode(main_node)?.as_bytes(),
ValueKind::Object,
) {
Some(node) => node,
@@ -771,7 +777,7 @@ impl JsonManipulator {
self.newline,
self.indent,
self.indent,
- JsonFile::encode(&name_owned),
+ JsonFile::encode(&name_owned)?,
self.format(&value_local, 1, false)?,
whitespace
),
@@ -787,7 +793,7 @@ impl JsonManipulator {
&format!(
"{{{}{}: {},{}{}{}",
whitespace,
- JsonFile::encode(&name_owned),
+ JsonFile::encode(&name_owned)?,
self.format(&value_local, 1, false)?,
self.newline,
self.indent,
@@ -812,7 +818,7 @@ impl JsonManipulator {
self.newline,
self.indent,
self.indent,
- JsonFile::encode(&name_owned),
+ JsonFile::encode(&name_owned)?,
self.format(&value_local, 1, false)?,
whitespace
);
@@ -843,7 +849,7 @@ impl JsonManipulator {
// no node content match-able
let node = match json_grammar::find_top_level_key(
self.contents.as_bytes(),
- JsonFile::encode(main_node).as_bytes(),
+ JsonFile::encode(main_node)?.as_bytes(),
ValueKind::Object,
) {
Some(node) => node,
@@ -1025,7 +1031,7 @@ impl JsonManipulator {
// main node content not match-able
let node = match json_grammar::find_top_level_key(
self.contents.as_bytes(),
- JsonFile::encode(main_node).as_bytes(),
+ JsonFile::encode(main_node)?.as_bytes(),
ValueKind::Array,
) {
Some(node) => node,
@@ -1161,7 +1167,7 @@ impl JsonManipulator {
// main node content not match-able
let node = match json_grammar::find_top_level_key(
self.contents.as_bytes(),
- JsonFile::encode(main_node).as_bytes(),
+ JsonFile::encode(main_node)?.as_bytes(),
ValueKind::Array,
) {
Some(node) => node,
@@ -1225,7 +1231,7 @@ impl JsonManipulator {
// no node content match-able
let node = match json_grammar::find_top_level_key(
self.contents.as_bytes(),
- JsonFile::encode(main_node).as_bytes(),
+ JsonFile::encode(main_node)?.as_bytes(),
ValueKind::Array,
) {
Some(node) => node,
@@ -1304,7 +1310,7 @@ impl JsonManipulator {
let content = self.format(&content, 0, false)?;
// key exists already
- let encoded_key = JsonFile::encode(key);
+ let encoded_key = JsonFile::encode(key)?;
let key_match = if decoded.as_array().and_then(|a| a.get(key)).is_some() {
json_grammar::find_top_level_key(
self.contents.as_bytes(),
@@ -1350,7 +1356,7 @@ impl JsonManipulator {
",{}{}{}: {}{}}}",
self.newline,
self.indent,
- JsonFile::encode(key),
+ JsonFile::encode(key)?,
content,
self.newline
),
@@ -1369,7 +1375,7 @@ impl JsonManipulator {
&format!(
"{}{}: {}{}}}",
self.indent,
- JsonFile::encode(key),
+ JsonFile::encode(key)?,
content,
self.newline
),
@@ -1390,7 +1396,7 @@ impl JsonManipulator {
}
// key exists already
- let encoded_key = JsonFile::encode(key);
+ let encoded_key = JsonFile::encode(key)?;
let key_match = json_grammar::find_top_level_key(
self.contents.as_bytes(),
encoded_key.as_bytes(),
@@ -1443,7 +1449,7 @@ impl JsonManipulator {
}
// Match the key only when its value is an empty object `{ <space> }`.
- let encoded_key = JsonFile::encode(key);
+ let encoded_key = JsonFile::encode(key)?;
let cb = self.contents.as_bytes();
let key_match =
json_grammar::find_top_level_key(cb, encoded_key.as_bytes(), ValueKind::Object)
@@ -1531,7 +1537,7 @@ impl JsonManipulator {
elems.push(format!(
"{}{}: {}",
str_repeat(&self.indent, (depth + 2) as usize),
- JsonFile::encode(key),
+ JsonFile::encode(key)?,
self.format(val, depth + 1, false)?
));
}
@@ -1546,7 +1552,7 @@ impl JsonManipulator {
));
}
- Ok(JsonFile::encode(&data))
+ JsonFile::encode(&data)
}
pub(crate) fn detect_indenting(&mut self) {
@@ -1707,7 +1713,7 @@ impl ManipulatorFormatter {
elems.push(format!(
"{}{}: {}",
str_repeat(&self.indent, (depth + 2) as usize),
- JsonFile::encode(key),
+ JsonFile::encode(key)?,
self.format(val, depth + 1, false)?
));
}
@@ -1722,6 +1728,6 @@ impl ManipulatorFormatter {
));
}
- Ok(JsonFile::encode(&data))
+ JsonFile::encode(&data)
}
}