Skip to content

Commit 886ced1

Browse files
committed
feat: improve CAS commands to handle both UTF-8 and binary data
1 parent 2fa1dd8 commit 886ced1

File tree

4 files changed

+36
-10
lines changed

4 files changed

+36
-10
lines changed

src/commands/serve.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ async fn execute_command(command: Command, frame: Frame, store: &Store) -> Resul
146146
Ok(pipeline_data) => {
147147
// Process each value as a .recv event
148148
for value in pipeline_data {
149-
let hash = store.cas_insert_sync(&value_to_json(&value).to_string())?;
149+
let hash = store.cas_insert_sync(value_to_json(&value).to_string())?;
150150
let _ = store.append(
151151
Frame::builder(
152152
format!("{}.recv", frame.topic.strip_suffix(".call").unwrap()),

src/nu/commands/cas_command.rs

+11-6
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,24 @@ impl Command for CasCommand {
5454
.store
5555
.cas_reader_sync(hash)
5656
.map_err(|e| ShellError::IOError { msg: e.to_string() })?;
57+
5758
let mut contents = Vec::new();
5859
reader
5960
.read_to_end(&mut contents)
6061
.map_err(|e| ShellError::IOError { msg: e.to_string() })?;
61-
let contents =
62-
String::from_utf8(contents).map_err(|e| ShellError::IOError { msg: e.to_string() })?;
6362

64-
Ok(PipelineData::Value(
65-
Value::String {
63+
// Try to convert to string if valid UTF-8, otherwise return as binary
64+
let value = match String::from_utf8(contents.clone()) {
65+
Ok(string) => Value::String {
66+
val: string,
67+
internal_span: span,
68+
},
69+
Err(_) => Value::Binary {
6670
val: contents,
6771
internal_span: span,
6872
},
69-
None,
70-
))
73+
};
74+
75+
Ok(PipelineData::Value(value, None))
7176
}
7277
}

src/nu/test_commands.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ mod tests {
9696
}
9797

9898
#[test]
99-
fn test_cas_command() {
99+
fn test_cas_command_string() {
100100
let (store, mut engine, _ctx) = setup_test_env();
101101
engine
102102
.add_commands(vec![Box::new(commands::cas_command::CasCommand::new(
@@ -112,6 +112,27 @@ mod tests {
112112
assert_eq!(content, "test content");
113113
}
114114

115+
#[test]
116+
fn test_cas_command_binary() {
117+
let (store, mut engine, _ctx) = setup_test_env();
118+
engine
119+
.add_commands(vec![Box::new(commands::cas_command::CasCommand::new(
120+
store.clone(),
121+
))])
122+
.unwrap();
123+
124+
// Test binary data retrieval
125+
let binary_data = vec![0, 159, 146, 150]; // Non-UTF8 bytes
126+
let hash = store.cas_insert_sync(&binary_data).unwrap();
127+
128+
let value = nu_eval(&engine, PipelineData::empty(), format!(".cas {}", hash));
129+
130+
// The value should be returned as binary
131+
assert!(matches!(value, Value::Binary { .. }));
132+
let retrieved_data = value.as_binary().unwrap();
133+
assert_eq!(retrieved_data, &binary_data);
134+
}
135+
115136
#[test]
116137
fn test_head_command() -> Result<(), Error> {
117138
let (store, mut engine, ctx) = setup_test_env();

src/store/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -452,11 +452,11 @@ impl Store {
452452
cacache::WriteOpts::new().open_hash_sync(self.path.join("cacache"))
453453
}
454454

455-
pub async fn cas_insert(&self, content: &str) -> cacache::Result<ssri::Integrity> {
455+
pub async fn cas_insert(&self, content: impl AsRef<[u8]>) -> cacache::Result<ssri::Integrity> {
456456
cacache::write_hash(&self.path.join("cacache"), content).await
457457
}
458458

459-
pub fn cas_insert_sync(&self, content: &str) -> cacache::Result<ssri::Integrity> {
459+
pub fn cas_insert_sync(&self, content: impl AsRef<[u8]>) -> cacache::Result<ssri::Integrity> {
460460
cacache::write_hash_sync(self.path.join("cacache"), content)
461461
}
462462

0 commit comments

Comments
 (0)