git.delta.rocks / jrsonnet / refs/commits / be790e9c5747

difftreelog

feat byte array specialization

Yaroslav Bolyukin2022-02-12parent: #20cd69c.patch.diff
in: master

2 files changed

modifiedcrates/jrsonnet-evaluator/src/builtin/mod.rsdiffbeforeafterboth
1use crate::function::StaticBuiltin;1use crate::function::StaticBuiltin;
2use crate::typed::{Any, PositiveF64, VecVal, M1};2use crate::typed::{Any, Bytes, PositiveF64, VecVal, M1};
3use crate::{3use crate::{
4 builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},4 builtin::manifest::{manifest_yaml_ex, ManifestYamlOptions},
5 equals,5 equals,
449}449}
450450
451#[jrsonnet_macros::builtin]451#[jrsonnet_macros::builtin]
452fn builtin_encode_utf8(str: IStr) -> Result<VecVal> {452fn builtin_encode_utf8(str: IStr) -> Result<Bytes> {
453 Ok(VecVal(453 Ok(Bytes(str.bytes().map(|b| b).collect::<Vec<u8>>().into()))
454 str.bytes()
455 .map(|b| Val::Num(b as f64))
456 .collect::<Vec<Val>>(),
457 ))
458}454}
459455
460#[jrsonnet_macros::builtin]456#[jrsonnet_macros::builtin]
461fn builtin_decode_utf8(arr: Vec<u8>) -> Result<String> {457fn builtin_decode_utf8(arr: Bytes) -> Result<IStr> {
462 Ok(String::from_utf8(arr).map_err(|_| RuntimeError("bad utf8".into()))?)458 Ok(std::str::from_utf8(&arr.0)
459 .map_err(|_| RuntimeError("bad utf8".into()))?
460 .into())
463}461}
464462
465#[jrsonnet_macros::builtin]463#[jrsonnet_macros::builtin]
485}483}
486484
487#[jrsonnet_macros::builtin]485#[jrsonnet_macros::builtin]
488fn builtin_base64(input: Either![Vec<u8>, IStr]) -> Result<String> {486fn builtin_base64(input: Either![Bytes, IStr]) -> Result<String> {
489 use Either2::*;487 use Either2::*;
490 Ok(match input {488 Ok(match input {
491 A(a) => base64::encode(a),489 A(a) => base64::encode(a.0),
492 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),490 B(l) => base64::encode(l.bytes().collect::<Vec<_>>()),
493 })491 })
494}492}
495493
496#[jrsonnet_macros::builtin]494#[jrsonnet_macros::builtin]
497fn builtin_base64_decode_bytes(input: IStr) -> Result<Vec<u8>> {495fn builtin_base64_decode_bytes(input: IStr) -> Result<Bytes> {
498 Ok(base64::decode(&input.as_bytes()).map_err(|_| RuntimeError("bad base64".into()))?)496 Ok(Bytes(
497 base64::decode(&input.as_bytes())
498 .map_err(|_| RuntimeError("bad base64".into()))?
499 .into(),
500 ))
499}501}
500502
501#[jrsonnet_macros::builtin]503#[jrsonnet_macros::builtin]
modifiedcrates/jrsonnet-evaluator/src/typed/conversions.rsdiffbeforeafterboth
--- a/crates/jrsonnet-evaluator/src/typed/conversions.rs
+++ b/crates/jrsonnet-evaluator/src/typed/conversions.rs
@@ -1,4 +1,7 @@
-use std::convert::{TryFrom, TryInto};
+use std::{
+	convert::{TryFrom, TryInto},
+	rc::Rc,
+};
 
 use gcmodule::Cc;
 use jrsonnet_interner::IStr;
@@ -295,6 +298,44 @@
 	}
 }
 
+/// Specialization
+pub struct Bytes(pub Rc<[u8]>);
+
+impl Typed for Bytes {
+	const TYPE: &'static ComplexValType =
+		&ComplexValType::ArrayRef(&ComplexValType::BoundedNumber(Some(0.0), Some(255.0)));
+}
+impl TryFrom<Val> for Bytes {
+	type Error = LocError;
+
+	fn try_from(value: Val) -> Result<Self> {
+		match value {
+			Val::Arr(ArrValue::Bytes(bytes)) => Ok(Self(bytes)),
+			_ => {
+				<Self as Typed>::TYPE.check(&value)?;
+				match value {
+					Val::Arr(a) => {
+						let mut out = Vec::with_capacity(a.len());
+						for e in a.iter() {
+							let r = e?;
+							out.push(u8::try_from(r)?);
+						}
+						Ok(Self(out.into()))
+					}
+					_ => unreachable!(),
+				}
+			}
+		}
+	}
+}
+impl TryFrom<Bytes> for Val {
+	type Error = LocError;
+
+	fn try_from(value: Bytes) -> Result<Self> {
+		Ok(Val::Arr(ArrValue::Bytes(value.0)))
+	}
+}
+
 pub struct M1;
 impl Typed for M1 {
 	const TYPE: &'static ComplexValType = &ComplexValType::BoundedNumber(Some(-1.0), Some(-1.0));