|
1 | 1 | use crate::{context::Context, error::RuntimeError, registry::HandlerFn}; |
| 2 | +use base64::Engine; |
2 | 3 | use tucana::shared::{value::Kind, ListValue, Value}; |
3 | 4 |
|
4 | 5 | pub fn collect_text_functions() -> Vec<(&'static str, HandlerFn)> { |
@@ -758,11 +759,81 @@ fn from_ascii(values: &[Value], _ctx: &mut Context) -> Result<Value, RuntimeErro |
758 | 759 | //TODO: Implement encode function , what about decode? UTF-8, 16 and 32 does not make sense |
759 | 760 |
|
760 | 761 | fn encode(values: &[Value], _ctx: &mut Context) -> Result<Value, RuntimeError> { |
761 | | - todo!("not implemented") |
| 762 | + let [Value { |
| 763 | + kind: Some(Kind::StringValue(value)), |
| 764 | + }, Value { |
| 765 | + kind: Some(Kind::StringValue(encoding)), |
| 766 | + }] = values |
| 767 | + else { |
| 768 | + return Err(RuntimeError::simple( |
| 769 | + "InvalidArgumentRuntimeError", |
| 770 | + format!( |
| 771 | + "Expected two numbers as arguments but received {:?}", |
| 772 | + values |
| 773 | + ), |
| 774 | + )); |
| 775 | + }; |
| 776 | + |
| 777 | + let encoded_string = match encoding.clone().to_lowercase().as_str() { |
| 778 | + "base64" => base64::prelude::BASE64_STANDARD.encode(value), |
| 779 | + _ => { |
| 780 | + return Err(RuntimeError::simple( |
| 781 | + "InvalidArgumentRuntimeError", |
| 782 | + format!("Unsupported encoding: {}", encoding), |
| 783 | + )) |
| 784 | + } |
| 785 | + }; |
| 786 | + |
| 787 | + Ok(Value { |
| 788 | + kind: Some(Kind::StringValue(encoded_string)), |
| 789 | + }) |
762 | 790 | } |
763 | 791 |
|
764 | 792 | fn decode(values: &[Value], _ctx: &mut Context) -> Result<Value, RuntimeError> { |
765 | | - todo!("not implemented") |
| 793 | + let [Value { |
| 794 | + kind: Some(Kind::StringValue(value)), |
| 795 | + }, Value { |
| 796 | + kind: Some(Kind::StringValue(encoding)), |
| 797 | + }] = values |
| 798 | + else { |
| 799 | + return Err(RuntimeError::simple( |
| 800 | + "InvalidArgumentRuntimeError", |
| 801 | + format!( |
| 802 | + "Expected two numbers as arguments but received {:?}", |
| 803 | + values |
| 804 | + ), |
| 805 | + )); |
| 806 | + }; |
| 807 | + |
| 808 | + let decoded_string = match encoding.clone().to_lowercase().as_str() { |
| 809 | + "base64" => match base64::prelude::BASE64_STANDARD.decode(value) { |
| 810 | + Ok(bytes) => match String::from_utf8(bytes) { |
| 811 | + Ok(string) => string, |
| 812 | + Err(err) => { |
| 813 | + return Err(RuntimeError::simple( |
| 814 | + "DecodeError", |
| 815 | + format!("Failed to decode base64 string: {:?}", err), |
| 816 | + )) |
| 817 | + } |
| 818 | + }, |
| 819 | + Err(err) => { |
| 820 | + return Err(RuntimeError::simple( |
| 821 | + "DecodeError", |
| 822 | + format!("Failed to decode base64 string: {:?}", err), |
| 823 | + )) |
| 824 | + } |
| 825 | + }, |
| 826 | + _ => { |
| 827 | + return Err(RuntimeError::simple( |
| 828 | + "InvalidArgumentRuntimeError", |
| 829 | + format!("Unsupported decoding: {}", encoding), |
| 830 | + )) |
| 831 | + } |
| 832 | + }; |
| 833 | + |
| 834 | + Ok(Value { |
| 835 | + kind: Some(Kind::StringValue(decoded_string)), |
| 836 | + }) |
766 | 837 | } |
767 | 838 |
|
768 | 839 | fn is_equal(values: &[Value], _ctx: &mut Context) -> Result<Value, RuntimeError> { |
@@ -1362,6 +1433,67 @@ mod tests { |
1362 | 1433 | assert_eq!(result, create_string_value("aba")); |
1363 | 1434 | } |
1364 | 1435 |
|
| 1436 | + #[test] |
| 1437 | + fn test_encode_invalid_parameter() { |
| 1438 | + let mut ctx = Context::new(); |
| 1439 | + let values = vec![create_string_value("aba")]; |
| 1440 | + let result = encode(&values, &mut ctx); |
| 1441 | + assert!(result.is_err()); |
| 1442 | + } |
| 1443 | + |
| 1444 | + #[test] |
| 1445 | + fn test_encode_invalid_encoding() { |
| 1446 | + let mut ctx = Context::new(); |
| 1447 | + let values = vec![create_string_value("aba"), create_string_value("gug")]; |
| 1448 | + let result = encode(&values, &mut ctx); |
| 1449 | + assert!(result.is_err()); |
| 1450 | + } |
| 1451 | + |
| 1452 | + #[test] |
| 1453 | + fn test_encode_correct() { |
| 1454 | + let mut ctx = Context::new(); |
| 1455 | + let values = vec![create_string_value("hello"), create_string_value("BASE64")]; |
| 1456 | + let result = encode(&values, &mut ctx).unwrap(); |
| 1457 | + assert_eq!( |
| 1458 | + result, |
| 1459 | + Value { |
| 1460 | + kind: Some(Kind::StringValue(String::from("aGVsbG8="))) |
| 1461 | + } |
| 1462 | + ); |
| 1463 | + } |
| 1464 | + |
| 1465 | + #[test] |
| 1466 | + fn test_decode_invalid_parameter() { |
| 1467 | + let mut ctx = Context::new(); |
| 1468 | + let values = vec![create_string_value("aba")]; |
| 1469 | + let result = decode(&values, &mut ctx); |
| 1470 | + assert!(result.is_err()); |
| 1471 | + } |
| 1472 | + |
| 1473 | + #[test] |
| 1474 | + fn test_decode_invalid_encoding() { |
| 1475 | + let mut ctx = Context::new(); |
| 1476 | + let values = vec![create_string_value("aba"), create_string_value("gug")]; |
| 1477 | + let result = decode(&values, &mut ctx); |
| 1478 | + assert!(result.is_err()); |
| 1479 | + } |
| 1480 | + |
| 1481 | + #[test] |
| 1482 | + fn test_decode_correct() { |
| 1483 | + let mut ctx = Context::new(); |
| 1484 | + let values = vec![ |
| 1485 | + create_string_value("aGVsbG8="), |
| 1486 | + create_string_value("BASE64"), |
| 1487 | + ]; |
| 1488 | + let result = decode(&values, &mut ctx).unwrap(); |
| 1489 | + assert_eq!( |
| 1490 | + result, |
| 1491 | + Value { |
| 1492 | + kind: Some(Kind::StringValue(String::from("hello"))) |
| 1493 | + } |
| 1494 | + ); |
| 1495 | + } |
| 1496 | + |
1365 | 1497 | #[test] |
1366 | 1498 | fn test_starts_with_true() { |
1367 | 1499 | let mut ctx = Context::new(); |
|
0 commit comments